Javascript - prompt keeps coming back after Ok is pressed - javascript

I have the following JavaScript configuration. It works well when it loads and keeps working well the first time I click on the button with id buttonKernel. This should run the function onPageLoad, which resets a grid presented on screen and reload the event handlers. The second time I click the button thought, after clicking OK on the prompt, it keeps prompting again. If I insist, it will eventually work.
I'm new to JavaScript, so that I don't know if this self calling function can be at the root of the problem.
$(document).ready(function(){
onPageLoad(16);
});
function onPageLoad(size){
genDiv(size);
$('.gridSquare').hover(function(){
$(this).css('background-color', 'red');
});
$('#buttonKernel').click(function(){
$(".gridSquare").css('background-color', 'yellow');
var input = prompt ("Enter a size for the grid", "16");
size = checkInp(input);
var list = document.getElementsByClassName("row");
for (var i = list.length - 1; 0 <= i; i--)
{
if (list[i] && list[i].parentElement)
list[i].parentElement.removeChild(list[i]);
};
onPageLoad(size);
});
}

every time you click, you add another click event handler.

Seems to be working fine for me?
http://jsfiddle.net/8atqub5k/1/
There are two unknown functions... genDiv(size) and checkInp(input) I have no clue what those do. Note: if there is a javascript error in either of those functions, generally javascript won't function at all on the rest of the site.
Are you aware of the Chrome browser Developer Tools? Way awesome tool for troubleshooting javascript (or html and CSS ) errors...
<style>
.gridSquare{
width: 100px;
height: 100px;
background-color: blue;
}
</style>
<button id="buttonKernel">Click here</button>
<div class="gridSquare">Test</div>
<script>
$(document).ready(function(){
onPageLoad(16);
});
function onPageLoad(size){
//genDiv(size);
$('.gridSquare').hover(function(){
$(this).css('background-color', 'red');
});
$('#buttonKernel').click(function(){
$(".gridSquare").css('background-color', 'yellow');
var input = prompt ("Enter a size for the grid", "16");
size = checkInp(input); // what is this function?
var list = document.getElementsByClassName("row");
for (var i = list.length - 1; 0 <= i; i--)
{
if (list[i] && list[i].parentElement)
list[i].parentElement.removeChild(list[i]);
};
// onPageLoad(size); // don't need this!
});
}
</script>

Related

How do you properly write a JavaScript "for" loop?

The GitHub Repository that I have linked will not be used for any other questions (it will not be changed except to help THIS question.... IT WILL ONLY BE USED FOR THIS QUESTION
Note: I have done my research and I believe that my code should work
Ok, so if you require the rest of my code to make a good judgement on this, feel free to go to: My Github Repository which is only going to be used for this 1 question. In the GitHub Repository, there is also a CSS file, but there is no problem with it, just included it so that you can see ALL the code.
Yes, I know that many people on this website do not like it when people include "GitHub" links; however, it is easier for me to explain if I do not have all the code sitting here making a mess (it is easier if I can narrow down what code is giving me an error
Ok, so this "for" loop:
var dropdown = document.getElementsByClassName("dropdown-btn");
var i;
for (i = 0; i < dropdown.length; i++) { //this is not getting called for some reason
dropdown[i].addEventListener("click", something());
alert("Please work");
}
is not actually running. When I put an "alert" above the for loop like:
var dropdown = document.getElementsByClassName("dropdown-btn");
var i;
alert("This works");
for (i = 0; i < dropdown.length; i++) { //this is not getting called for some reason
dropdown[i].addEventListener("click", something());
alert("This does not work");
}
The alert is called as soon as the method that the "for" loop is in, is called. I guess to explain my question, is there anything wrong with my "for" loop? (This works in a different .html file, so I am not sure why it is not working in my current workspace.)
UPDATE (February 18, 2019):
Ok so I found what is causing the error.
For the person that commented and suggested that I use "console.log(dropdown.length);", this brought up an unexpected error:
function something(){
this.classList.toggle("active");
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display === "block") {
dropdownContent.style.display = "none";
} else {
dropdownContent.style.display = "block";
}
}
As I originally said, this works in another file, but for some reason, it says that in "this.classList.toggle("active);", "toggle" is undefined. Is this supposed to be defined in this file, or is it like i think and a default "function"? Through all of my research, and through all the knowledge I have of the language of JavaScript, I am confident that it is a default "function", and unless someone can prove me wrong, I don't understand why this is not working.
The problem is that you are passing a function in as a parameter without wrapping it in a calling function.
There are two ways you would make this work.
Remove the () from the something function and call the alert inside of something
for (i = 0; i < dropdown.length; i++) { //this is not getting called for some reason
dropdown[i].addEventListener("click", something)
}
something () {
alert('this is working')
...
}
Put a single function call in your event handler and place both function calls inside
for (i = 0; i < dropdown.length; i++) { //this is not getting called for some reason
dropdown[i].addEventListener("click", function () {
something();
alert("This works");
})
}
Here is an example:
You are calling something instead of just passing the callable function when trying to add the eventListener. Remove the parentheses.
var dropdown = document.getElementsByClassName("dropdown-btn");
var i;
for (i = 0; i < dropdown.length; i++) { //this is not getting called for some reason
dropdown[i].addEventListener("click", something);
}
function something() {
this.classList.toggle("active");
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display === "block") {
dropdownContent.style.display = "none";
} else {
dropdownContent.style.display = "block";
}
}
<a class="dropdown-btn" href="#">Button 1</a>
<div style="display:none;">Dropdown Content Here</div>
<br />
<a class="dropdown-btn" href="#">Button 2</a>
<div style="display:none;">Dropdown Content Here</div>
I was watching the repository on GitHub, and I saw that there are a lot of errors in your html part, so that the JS part can not work.
Just about this loop, the current html part is:
<button class="dropdown-btn" onclick="drop()">OUR STORY
<i class="fa-caret-down"></i>
</button>
So that the first time the drop () function creates a new event listener on the button, but does not call it.
If there is a second click on this button then 2 actions are then launched: the first adds again a new event listener click on the button,
the second is the triggering of the event listener created the first time.
There are 2 possible solutions
Solution 1
<button class="dropdown-btn" onclick="something()">OUR STORY
<i class="fa-caret-down"></i>
</button>
Solution 2
<button class="dropdown-btn" >OUR STORY
<i class="fa-caret-down"></i>
</button>
With in the part JS = ( ! remove function drop() declaration ! )
var dropdown = document.getElementsByClassName("dropdown-btn");
for (let i = 0, iMax=dropdown.length ; i < iMax ; i++) {
dropdown[i].addEventListener("click", something);
}
for helping understand why your code is wrong, please try this sample code
var Compteur = 0;
function something(){
console.log('call on something()', ++Compteur);
}
function drop(){
var dropdown = document.getElementsByClassName("dropdown-btn");
for (let i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener("click", something);
console.log( 'adding event Listener on one dropdown-btn ', ++Compteur);
}
}
<button class="dropdown-btn" onclick="drop()">OUR STORY </button>
Here is your problem.
Ask yourself why are you getting this.classList as undefined?
If you looked further you would find that this is the window object which has no classList . Now ask yourself why the window object?
It is because something() is an event listener that should be called in response to an event. In the line dropdown[i].addEventListener("click", something()); , you aren't assigning something() as an event handler, you are calling the method, without an event, so there is no this.classList as this is the window object.
As other answers have mentioned you need to change this to:
dropdown[i].addEventListener("click", something);
Which will assign the event something() to the click event, without calling it.
Complete Example
function something(){
console.log(this); //For Debug prurposes
this.classList.toggle("active");
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display === "block") {
dropdownContent.style.display = "none";
} else {
dropdownContent.style.display = "block";
}
}
/* Loop through all dropdown buttons to toggle between hiding and showing its dropdown content - This allows the user to have multiple dropdowns without any conflict */
function drop(){
var dropdown = document.getElementsByClassName("dropdown-btn");
var i;
for (i = 0; i < dropdown.length; i++) { //this is not getting called for some reason
dropdown[i].addEventListener("click", something);
console.log("Please wokrk");
}
}
.sidenav a, .dropdown-btn {
padding: 6px 8px 6px 16px;
text-decoration: none;
font-size: 20px;
color: #818181;
display: block;
border: none;
background: none;
width: 100%;
text-align: left;
cursor: pointer;
outline: none;
}
.active {
background-color: green;
color: white;
}
.dropdown-container {
display: none;
background-color: #262626;
padding-left: 8px;
}
<button class="dropdown-btn" onclick="drop()">OUR STORY
<i class="fa-caret-down"></i>
</button>
<div class="dropdown-container">
ABOUT US
COMMUNITY
HUMANITARIAN ACTION
</div>
On a side note, it is quite unusual to use inline events like onClick=drop() to then bind other event listeners to the same element. It is actually best practice to avoid inline javascript all together.
In the future, please include all code relevant to the question, in the question itself. As I mentioned in a comment it makes it easier for us to help you.

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

How to dynamically change tab title when it is not selected?

I want to display dynamic information (score) in the window tab of a javascript games running in a browser (chrome) : my goal is to run several instances of the game in different tabs, running in parallel, and to be able to see the current scores in the tab titles. I tried :
document.title = score
... but it works only in the selected tab, the other one are not refreshed until selected (although the games are running well in background).
==> is there a way to force the update of the tab titles... even if not selected ?
I found couple of same questions on the http://stackoverflow.com but they did not work for me.
You can find your solution here: http://www.raymondcamden.com/2010/10/19/Using-JavaScript-to-update-the-browser-window-title-when-the-user-is-away
So, basically that kind of code will work:
var focused = true;
var baseTitle = "";
var chatsMissed = 0;
//I'm the fake function that represents some process. We randomly determine if a new chat happened
function fakeStuff() {
if(Math.random() > 0.5) {
if(!focused) {
chatsMissed++;
window.document.title = baseTitle + " ("+chatsMissed+")";
}
}
}
$(document).ready(function() {
//store the base title
baseTitle = window.document.title;
//When the window is focused...
$(window).focus(function() {
focused = true;
// window.document.title = baseTitle;
//chrome bug: http://heyman.info/2010/oct/7/google-chrome-bug-when-setting-document-title/
setTimeout(function() {
document.title = baseTitle;
}, 100);
chatsMissed = 0;
});
//When the window is blurred...
$(window).blur(function() {
focused = false;
});
//setup a process
window.setInterval('fakeStuff()',2000);
})
Unfortunately JSfiddle do not support title changing. But I tested, and it works.

Javascript Onclick vs Onmousedown Race Condition

I have a SUBMIT and SAVE button for a form that are by default listening for Onclick events.
When the form is SUBMITTED OR SAVED - the page resets the scroll position to the TOP of the page.
Recently the users of the applications have requested that the page stay at the bottom of the page where the buttons are located for only a subset of forms.
(These buttons are used across hundreds of other forms so I cannot change the reset of the scrolling globally.)
So the solution that I am trying to implement involves a couple hidden input fields and a few event listeners.
I have added an onmousedown event for these buttons, like so -
// Submit and Save button listeners
var globalButtons;
if (v_doc.getElementsByClassName) {
globalButtons = v_doc.getElementsByClassName('globalbuttons');
}
// Internet Explorer does not support getElementsByClassName - therefore implement our own version of it here
else {
globalButtons = [];
var myclass = new RegExp('\\b'+'globalbuttons'+'\\b');
var elem = v_doc.body.getElementsByTagName("input");
for (var i = 0; i < elem.length; i++) {
var classes = elem[i].className;
if (myclass.test(classes)) {
globalButtons.push(elem[i]);
}
}
}
for (var gb = 0; gb < globalButtons.length; gb++) {
if (globalButtons[gb].name == 'methodToCall.route' ||
globalButtons[gb].name == 'methodToCall.save') {
if(globalButtons[gb].addEventListener) { //all browsers except IE before version 9
globalButtons[gb].addEventListener("mousedown", function(){flagSpecialScrollOnRefresh()},false);
}
else {
if(globalButtons[gb].attachEvent) { //IE before version 9
globalButtons[gb].attachEvent("onmousedown",function(){flagSpecialScrollOnRefresh()});
}
}
}
else { continue; }
}
This code is located in a function called attachButtonListeners
Next, I defined my handler like so and placed it into another function that gets called each time my page is being loaded -
function checkSpecialScrollCase() {
var spfrm = getPortlet();
var sp_doc = spfrm.contentDocument ? spfrm.contentDocument: spfrm.contentWindow.document;
var specialScrollExists = sp_doc.getElementById(docTypeButton).value;
if (specialScrollExists == "YES") {
sp_doc.getElementById(docTypeButton).value = 'NO';
}
// else - nothing to do in this case
}
docTypeButton = REQS_BUTTONS
And it references the following element at the bottom of my JSP page -
<input type="hidden" id="REQS_BUTTONS" value="NO"/>
<a name="anchorREQS"></a>
Notice the anchor tag. Eventually, I need to add the location.hash call into my handler so that I scroll to this location. That part is irrelevant at this point and here is why.
Problem -
My flagSpecialScrollOnRefresh function is NOT setting the value to YES when it should be.
I believe my onClick event is happening too fast for my onmousedown event from happening.
Evidence -
If I place an alert statement like so -
function flagSpecialScrollOnRefresh() {
var scfrm = getPortlet();
var sc_doc = scfrm.contentDocument ? scfrm.contentDocument: scfrm.contentWindow.document;
alert("BLAH!");
sc_doc.getElementById(docTypeButton).value = "YES";
}
And then I examine the element using Firebug - the value is getting SET!
Once I take out the alert - no go!
How do I ensure that my mousedown event gets executed first? Or is this even the problem here????
mousedown is part of a click event.
Whatever you are doing with click events now should be moved to the submit event on the form. That way you can use mousedown, mouseover, or even click on the buttons to do whatever you want.

Categories

Resources