Single Click on Check all button issue - javascript

I have a check all button on click it will select all the checkboxes. But on my display page i have 30000 checkboxes which is giving me page unresponsive on click on Check All button. Can somebody please help on this.
function js_select_all(btn,theForm){
if (btn.value == "Check All") {
var checkval = "checked";
if (js_one_row(theForm.circSelected)) {
theForm.circSelected.checked = checkval;
} else {
for (var i=0; i < theForm.circSelected.length; i++){
theForm.circSelected[i].checked = checkval;
}
}
btn.value ="Uncheck All";
}else {
if (js_one_row(theForm.circSelected)) {
theForm.circSelected.checked = false;
} else {
for (var i=0; i < theForm.circSelected.length; i++){
theForm.circSelected[i].checked = false;
}
}
btn.value = "Check All";
}
}
Can soembody help me to acheive the result in fastest way possible.I am working on a webtoolkit which supports only HTML,CSS and JS.

Break the task into smaller chunks, and run them after short delays using setTimeout
This allows the browser to remain responsive. Presumably it is not essential that the tickboxes all change state immediately? The user will presumably be happy that the computer is ticking the boxes, even if it takes a few moments, since otherwise the user would have to do it himself/herself.
Here is an example where we break it into chunks of 100 check boxes, and each chunk done at an interval of 1000 ms.
const chunkSize=100;
const intervalBetweenChunksMs = 1000;
for (var i=0; i < theForm.circSelected.length ; i+=chunkSize) {
console.log("Creating chunk starting at",i)
setTimeout(function(start){for(var j=start; j<Math.min(i+chunkSize,33); j++)
{
console.log("Doing item number", j);
theForm.circSelected[j].checked = checkval;
}
}(i),(1 + theForm.circSelected.length/chunkSize)*intervalBetweenChunksMs )
}
If this works in principle, you will probably want to try smaller intervals, so that the complete "wave" of checking is done in a reasonable timeframe.
I have put in a "1+" so that the first chunk (starting at item number 0) only occurs after one interval. If this introduces an unacceptable lag before the first visible change, then remove the "1+".

Related

uninterrupted setInterval function

I wanted to display some divs on my HTML page with some animations. So I decided to use the setInterval method to increases the opacity of all of my div. I wrote the below code in order to do this (the toggleAll function is run at the beginning)
var tab = ["lien","contact","comp_info","comp_langue","apropos","loisir","etudes","exp_pro","projet"];
function increaseOpacityDiv(id,opacityMax){
console.log("fonction appelée : increaseOpacityDiv, opacity max :"+opacityMax);
if(document.getElementById(id).style.opacity >= opacityMax){
console.log("entré ! ");
clearInterval(boucle);
document.getElementById(id).style.opacity = opacityMax;
debugger;
}else{
recup = parseFloat(document.getElementById(id).style.opacity+0) + 0.01;
document.getElementById(id).style.opacity = recup;
}
}
function decreaseOpacityDiv(id){
console.log("fonction appelée : decreaseOpacityDiv");
if(document.getElementById(id).style.opacity <= 0){
clearInterval(boucle);
document.getElementById(id).style.opacity = 0;
}else{
recup = parseFloat(document.getElementById(id).style.opacity) - 0.01;
document.getElementById(id).style.opacity = recup;
}
}
function toggleAll(){
console.log("fonction appelée : toggleAll");
if(all){
console.log("faire disparaitre");
for (var i=0;i<tab.length;i++){
boucle = setInterval(decreaseOpacityDiv,5,tab[i]);
}
all=0;
}else{
console.log("faire apparaitre");
for (var i=0;i<tab.length;i++){
boucle = setInterval(increaseOpacityDiv,5,tab[i],1);
}
all=1;
}
}
It works, the browser displays correctly the divs. However I can't disappeared them, in the same way as I displayed them. I found out that my toggleAll function made a lot of setInterval and I can't stop all of them, so the increaseOpacityDiv is run like every 5ms. And the clearInterval method can just stop the last loop made by the setInterval, not the others. This is shown by this below :
console log
Do you know a way I can show my divs then stop all the setInterval ?

How to set a maximum amount of clicks on an order button for each item specifically? (JavaScript)

I'm trying to implement a functionality where the user can only order a set amount of times (let's take 5 times for example) before an alert shows up saying that the product he is trying to order has ran out of stock.
He can still of course, order other product that haven't been clicked on 5 times.
The problem I'm facing is that I don't know how to keep count of each order button (an anchor acting as a button) specifically.
I tried implementing that functionality and it does show an alert, but it takes count of all order buttons clicked.
This is how my functions looks:
let counter = 0; //global variable
function order_func() {
let every_product= document.querySelectorAll(".all_prods");
for (let each_prod = 0; each_prod < every_product.length; each_prod++) {
every_product[each_prod].addEventListener("click", function (e) {
if(count_stuff < 10){
add_it(e, each_prod); //e to preventDefault() and console.log "each_prod"
count_stuff++;
}else{
out_of_stock(e); //shows the alert it takes the event as argument to prevent default behavior.
}
});
}
}
add_it() is just a function that console.log()'s the product.
I'm only using vanilla JS, I don't want to use any other libraries for this :)
you can use data attribute to store temp values in page. take a look on this example using JQuery.
<!-- index.html -->
Order
<script>
$('#order-btn').click(function() {
var maxCounts = this.data('maxCounts');
var count = this.data('count');
if (count >= maxCount) {
alert('you cant order any more');
return;
}
this.data('count',count++);
// other logic .e.g Ajax call
})
</script>
you can do it using vanilla JS also:
<script>
let counter = 0; //global variable
function order_func() {
let every_product= document.querySelectorAll(".all_prods");
for (let each_prod = 0; each_prod < every_product.length; each_prod++) {
every_product[each_prod].addEventListener("click", function (e) {
var count_stuff = e.target.dataset.count; // or this.dataset.count
var max_count = e.target.dataset.maxCounts; // or this.dataset.maxCounts
if(count_stuff < max_count){
add_it(e, each_prod);
e.target.dataset.count = count_stuff++;
}else{
out_of_stock(e);
}
});
}
}
</script>

Delay Display of Text in Qualtrics using Javascript

(This is related to the unanswered question https://stackoverflow.com/questions/26745762/delaying-presentation-of-text-in-qualtrics)
I am working on a Qualtrics survey. I want to delay some text (say, text) being displayed - it should be hidden for 5 seconds, then display.
I found a resource here - Javascript for Qualtrics - that I can't get to work.
Drawing from this example, I try to replicate it by delaying the display of a photo. I do this to see if I can get this working before I go on to delaying the display of text as opposed to a photo.
In the HTML part, I put:
Time: <span id="time1">30</span><br>
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/%C3%81guila_calva.jpg/1280px-%C3%81guila_calva.jpg" style="width: 133px; height: 115px;" class='pic1' />
In the Javascript part, I have:
started = false;
function countDown1() {
if (!started)
started = true;
else {
var value1 = parseInt($('time1').innerHTML);
$('time1').innerHTML = value1 - 1;
if (value1 == 26) {
var styling1 = document.getElementsByClassName('pic1')[0];
styling1.style.display = "none";
}
}
setTimeout(countDown1, 1000);
}
Event.observe(window, 'load', countDown1);
For some reason, nothing happens at all with the timer or the photo.
Do I need to wrap the above Javascript in:
Qualtrics.SurveyEngine.addOnload(function()
{
});
I tried this as well, but no change.
So I really have two questions. 1. How do I modify the above code to get it working. And 2. How do I modify the working version of the code to display text after a certain amount of time?
You're making it more complex than need be.
Here is example html for the question:
This is a question. <span id="hiddentext" style="display:none">This text
will display after five seconds.</span>
Here is the javascript for the question:
Qualtrics.SurveyEngine.addOnload(function()
{
setTimeout("$('hiddentext').style.display = 'inline'",5000);
});
This hides the radiobuttons or Choices in a multiple choice question for 2 seconds. If you need to hide the next button as well you can add a Timing question from the ones already provided in Qualtrics and set it to "Enable submit after (seconds)".
Qualtrics.SurveyEngine.addOnload(function() {
var QID = this.questionId;
console.log(QID);
for (var i = 1; i < 4; i++) {
document.getElementById( QID + "-" + i + "-label" ).style.display="none";
}
(function(delay_container){
for (var i = 1 ; i < 4 ; i ++){
document.getElementById(QID + "-" + i + "-label").style.display="block";
}
}).delay(2,this.questionContainer);
});
Let's say you have two sentences that are two separate Descriptive text boxes. And you want the second box to appear some seconds after the first. The following worked for me when assigned for the second box. The same code works for following boxes as well. You can again put a Timing question at the end of the page to hide Next button.
Qualtrics.SurveyEngine.addOnload(function() {
var QID = this.questionId;
console.log(QID);
for (var i = 1; i < 4; i++) {
document.getElementById( QID).style.display="none";
}
(function(delay_container){
for (var i = 1 ; i < 4 ; i ++){
document.getElementById(QID).style.display="block";
}
}).delay(2,this.questionContainer);
});

Page hangs up, too much to search

I used PHP to create an HTML page, which compiles a list of data points and pushes them into an array, declares the array in the header, and also echo's a huge list of form input objects into the body.
The list I'm working with is just under 15,000 lines which are put into 1 array.
I more or less created a search box that when I blur() an action is supposed to occur, Javascript function is supposed to search through the array and hide unmatched form options and display matches. This seems to work fine up to 5000 but if I have it run through all 15000 array items it hangs up and freezes.
I'm currently hosting it on a free site while I test... here is the link to the actual page TEST PAGE that hangs up
I'm including a snippet of the JS code with a truncated array so you don't have to scroll for thousands of lines.
<script type="text/javascript" >
var array_ICDDx = new Array('[ICD Code] Diagnosis','[001.0] Cholera due to vibrio cholerae','[001.1] Cholera due to vibrio cholerae el tor','[001.9] Cholera, unspecified','[002.0] Typhoid fever','[002.1] Paratyphoid fever A','[002.2] Paratyphoid fever B','[002.3] Paratyphoid fever C','[002.9] Paratyphoid fever, unspecified','[003.0] Salmonella gastroenteritis','[003.1] Salmonella septicemia','[003.20] Localized salmonella infection, unspecified','[003.21] Salmonella meningitis','[003.22] Salmonella pneumonia','[003.23] Salmonella arthritis','[003.24] Salmonella osteomyelitis',[...GOES ON FOREVER ~15000 ARRAY VALUES...]);
function searchICDDx(ICDDx,line_start,line_end) {
for (var a = line_start; a < line_end; a++) {
var ICDDx_check = array_ICDDx[a].toLowerCase();
var Row = "R" + a;
if (ICDDx_check.search(ICDDx) >= 0) {
document.getElementById(Row).style.display = "block";
}
else {
document.getElementById(Row).style.display = "none";
}
}
if (line_end < array_ICDDx.length) {
line_end += 1000;
if (line_end > array_ICDDx.length) { line_end = array_ICDDx.length; }
var timer = setTimeout(searchICDDx(ICDDx,a,line_end),100);
// searchICDDx(ICDDx,a,line_end);
}
// else if (line_end >= array_ICDDx.length) {
// clearTimeout(timer);
return;
// }
}
function searchICD() {
var find_ICD = Coder.elements['ICD'].value;
if (find_ICD != "") {
document.Coder.Dx.value = "";
find_ICD = find_ICD.toLowerCase();
searchICDDx(find_ICD,1,1000);
}
}
function searchDx() {
var find_Dx = Coder.elements['Dx'].value;
if (find_Dx != "") {
document.Coder.ICD.value = "";
find_Dx = find_Dx.toLowerCase();
searchICDDx(find_Dx,1,1000);
}
}
</script>
It doesn't appear to be an issue with the code not functioning. As I mentioned, if I limit the search to just 1000 array values it seems to work, its the massive amount of array values that is killing the page.
Any suggestions?
Thank you in advance!
With this many data points, you should probably do this on the server. However, you can try the following:
instead of using a for loop (which completely freezes the browser until it is done), use a setInterval that checks a new result every 5 ms or so. Periodically, check if all the results have been searched, and clear the interval if so. It will still take a bit to search, but won't freeze the browser.
search only until you have a set number of results (40 or so), and store the last index of the array that was searched. Wait to load more searches until the user scrolls down the page.
Also, you should probably implement an infinite scroll for displaying results. My browser froze and had to be restarted just opening the link you attached.
Update: if you don't want the items displayed until after you search, you should have no items on the page initially and add them when they match the search. This prevents the initial lag, prevents you from having to change the visibility of every element, and reduces the number of elements on the page (which causes issues).
Thank you for all your input and suggestions.
I went back and took out all of entries when listed in the form. Then I had JS create a list of checkbox inputs based on all the positive results and element.innerHTML the results. The array is still a huge list on client side through which the JS searches for matches. I updated the code in the link from my original post to show the faster and working result.
<script type="text/javascript" >
var array_ICDDx = new Array('[icd code] diagnosis','[001.0] cholera due to vibrio cholerae','[001.1] cholera due to vibrio cholerae el tor','[001.9] cholera, unspecified','[002.0] typhoid fever','[002.1] paratyphoid fever a',[...etc...]);
function searchICDDx(array_Results,ICDDx,line_start,line_end) {
for (var a = line_start; a < line_end; a++) {
if (array_ICDDx[a].indexOf(ICDDx) >= 0) {
array_Results.push("<span style='display:block' ><input type='checkbox' value='"+array_ICDDx[a]+"' >"+array_ICDDx[a]+"</span>");
}
}
if (line_end < array_ICDDx.length) {
line_end += 1000;
if (line_end > array_ICDDx.length) { line_end = array_ICDDx.length; }
searchICDDx(array_Results,ICDDx,a,line_end);
}
else if (line_end >= array_ICDDx.length) {
var string_Results = array_Results.join("\n");
document.getElementById("Results_here").innerHTML = string_Results;
return;
}
}
function searchICD() {
var array_Results = new Array();
var find_ICD = Coder.elements['ICD'].value;
if (find_ICD != "") {
document.Coder.Dx.value = "";
find_ICD = find_ICD.toLowerCase();
searchICDDx(array_Results,find_ICD,1,1000);
}
}
function searchDx() {
var array_Results = new Array();
var find_Dx = Coder.elements['Dx'].value;
if (find_Dx != "") {
document.Coder.ICD.value = "";
find_Dx = find_Dx.toLowerCase();
searchICDDx(array_Results,find_Dx,1,1000);
}
}
</script>
In the past I've had poor results with forms and innerHTML added options, which I'll tackle another time when I try to move this code into the larger project.
Thank you again

Javascript Logic In a loop/if statement

I have this function (transComplete) which performs the task of highlighting a relevant indicator showing the user which page they are on, each element of these controllers/indicators represents a page and will highlight appropriately.
This works independently however when I introduce a click function that allows to interact with indicators to move between pages it navigates correctly but does not highlight as needed (works only every two clicks) which leads me to believe its a logic issue in my code.
The boolean logic of true/false is the cause, the highlighting only occurs on the 'true' cases of the variable "isOnSecond" so I essentially need a solution that always highlights the relevant controller when clicked
The main function is below:
function transComplete() {
slideTransStep = 0;
crtSlideIndex = nextSlideIndex;
// for IE filters, removing filters re-enables cleartype
if (nextSlide.style.removeAttribute) {
nextSlide.style.removeAttribute("filter");
// show next slide
showSlide((crtSlideIndex >= totalSlides) ? 1 : crtSlideIndex + 1);
//Highlights a nav circle every two transitions as the boolean alternates
if (isOnSecond == true) {
//unhighlight all controls
for (var i = 0; i < slidesControllersCollection.length; i++) {
if (slidesControllersCollection[i].className === slideHighlightClass) {
slidesControllersCollection[i].className = "";
}
// highlight the control for the next slide
document.getElementById("slide-control-" + crtSlideIndex).className = slideHighlightClass;
}
isOnSecond = false;
}
else {
isOnSecond = true;
}
}
The onclick Function:
function clickSlide(control) {
showSlide(Number(control.id.substr(control.id.lastIndexOf("-")+1)),true);
}
I think you made your trans function when you were still iterating from one page to the very next, now that user can go any frame, you need to clear any highlight each time, then put it again on current one.
Or rather, for performance's sake, store the last highlighted, then highlight the new one.
But ... why not just drop the 'onSecond' logic ? It doesn't make much sense for the user to get a highlight one time over two only...
Anyway if you keep it the onSecond idea, logic would be :
if (lastHighlighted) lastHighlighted.className = "";
if (isOnSecond) {
lastHighLighted = document.getElementById("slide-control-" + crtSlideIndex);
lastHighLighted.className = slideHighlightClass;
} else {
lastHighLighted = null;
}
isOnSecond = ! isOnSecond;
But in fact i wonder if what you want is not the version without onSecond logic :
if (lastHighlighted) lastHighlighted.className = "";
lastHighLighted = document.getElementById("slide-control-" + crtSlideIndex);
lastHighLighted.className = slideHighlightClass;
(Rq declare lastHighlighted as a var so it can be in the scope of transComplete)

Categories

Resources