Jasmine test is not detecting that button has been clicked - html

I have written a Jasmine test that clicks on the first error message in a list and closes it. It then checks that the number of errors has reduced to the expected amount:
it('should close the error if the errors close button is clicked', function() {
element.all(by.repeater('error in errorList')).then(function(errorList) {
errorList[0].element(by.id('error0')).then(function(error0) {
error0.click();
var arrayLength = errorList.length;
expect(arrayLength).toEqual(1);
});
});
});
When I run this I get the message Expected 2 to equal 1. 2 is the length of the error array at the start of the test. If I manually recreate this, the error message definitely closes when clicking anywhere within error0. Is it possible that clicking this takes some time and this isn't registered by the time the expect statement is run?
Here is the relevant part of the HTML:
<a class="po-cross-link" href="" ng-click="closeError(error)" id="{{'error'+$index}}">
<img class="po-cross" src="\assets\black-cross.png" alt="close">
</a>
Thanks

I guess you are changing the model in the click handler but you expect the DOM elements to be changed instantly. Angular needs a $digest cycle to update the DOM according to the model, so I suggest you run scope.$digest() after clicking. If you don't have a scope in your test, you can also use the $rootScope.

Thanks...I sussed it shortly after posting. Similar in principle the other answer given I think. It's because I needed to get the most recent version of the DOM. I added in a second asynchronous function as follows:
it('should close the error if the errors close button is clicked', function() {
element.all(by.repeater('error in errorList')).then(function(errorList) {
errorList[0].element(by.id('error0')).then(function(error0) {
error0.click();
element.all(by.repeater('error in errorList')).then(function(errorListNew) {
var arrayLength = errorListNew.length;
expect(arrayLength).toEqual(1);
});
});
});
});

Related

I keep receiving an error message when I create a DOM Event in JS

I am learning DOM Events and I keep receiving an error message.
my code is the top half works perfectly however the remove section keeps getting the following "Uncaught TypeError: document.getElementByClassName is not a function
at js.js:7"
any advice much appreciated.
`var button= document.getElementById("button");
button.addEventListener('click', function() {
alert ("Click!!!!!!!!!!");
});
var remove = document.getElementByClassName("remove");
remove.addEventListener('click', function() {
return ("removed!!!!!!!!!!");
});`
You may have a type error, remember you are referencing many dom elements and not just one
it should be getElementsByClassName not getElementByClassName
which you can then loop over the elements using array method to append listener on each. Example code below;
let remove = document.getElementsByClassName("remove");
remove.forEach(elem => {
elem.addEventListener("click",myEventHandler);
});

How to autorun functions on JavaScript/HTML

function myFunction() {
alert("Lol");
}
<button onclick="myFunction()">Click Here</button>
That's my code and I am wanting this to run automatically when opened up. It should run the function and a pop up box will open in 0.5 seconds. When the pop up box is closed, another one is opened in 0.5 seconds.Just to clarify, this is mainly used for pranking my friend and I had the working code but my system crashed and the file got corrupted/other, either way it no longer works and I can't seem to remember the code exactly. Please can someone help me get this code up and working again. I only want it to open a pop up box and nothing else as I know this could be used as a method to spam others however this will be used fro nothing but me and my friends work. Thank you again.P.S. I have had to add a space between my and my as other wise it would not let me post this question.
Use this to launch the code when a page with this script load :
window.onload = function() {
setInterval('alert("Lol")', 500); //Actualisation 0.5s
};
Or this to use the button :
function myFunction() {
setInterval('alert("Lol")', 500);
}
If u want to stop this interval, not useful here but good to know
var intervalID = setInterval('alert("Lol")', 500);
//Later in the process
clearInterval(intervalID);
eventlisteners usually work:
document.addEventListener("DOMContentLoaded", function(event) {
//show popup
});

How to send a single request through p:commandButton inside p:dialog? [duplicate]

I have following jQuery code to prevent double clicking a button. It works fine. I am using Page_ClientValidate() to ensure that the double click is prevented only if the page is valid. [If there are validation errors the flag should not be set as there is no postback to server started]
Is there a better method to prevent the second click on the button before the page loads back?
Can we set the flag isOperationInProgress = yesIndicator only if the page is causing a postback to server? Is there a suitable event for it that will be called before the user can click on the button for the second time?
Note: I am looking for a solution that won't require any new API
Note: This question is not a duplicate. Here I am trying to avoid the use of Page_ClientValidate(). Also I am looking for an event where I can move the code so that I need not use Page_ClientValidate()
Note: No ajax involved in my scenario. The ASP.Net form will be submitted to server synchronously. The button click event in javascript is only for preventing double click. The form submission is synchronous using ASP.Net.
Present Code
$(document).ready(function () {
var noIndicator = 'No';
var yesIndicator = 'Yes';
var isOperationInProgress = 'No';
$('.applicationButton').click(function (e) {
// Prevent button from double click
var isPageValid = Page_ClientValidate();
if (isPageValid) {
if (isOperationInProgress == noIndicator) {
isOperationInProgress = yesIndicator;
} else {
e.preventDefault();
}
}
});
});
References:
Validator causes improper behavior for double click check
Whether to use Page_IsValid or Page_ClientValidate() (for Client Side Events)
Note by #Peter Ivan in the above references:
calling Page_ClientValidate() repeatedly may cause the page to be too obtrusive (multiple alerts etc.).
I found this solution that is simple and worked for me:
<form ...>
<input ...>
<button ... onclick="this.disabled=true;this.value='Submitting...'; this.form.submit();">
</form>
This solution was found in:
Original solution
JS provides an easy solution by using the event properties:
$('selector').click(function(event) {
if(!event.detail || event.detail == 1){//activate on first click only to avoid hiding again on multiple clicks
// code here. // It will execute only once on multiple clicks
}
});
disable the button on click, enable it after the operation completes
$(document).ready(function () {
$("#btn").on("click", function() {
$(this).attr("disabled", "disabled");
doWork(); //this method contains your logic
});
});
function doWork() {
alert("doing work");
//actually this function will do something and when processing is done the button is enabled by removing the 'disabled' attribute
//I use setTimeout so you can see the button can only be clicked once, and can't be clicked again while work is being done
setTimeout('$("#btn").removeAttr("disabled")', 1500);
}
working example
I modified the solution by #Kalyani and so far it's been working beautifully!
$('selector').click(function(event) {
if(!event.detail || event.detail == 1){ return true; }
else { return false; }
});
Disable pointer events in the first line of your callback, and then resume them on the last line.
element.on('click', function() {
element.css('pointer-events', 'none');
//do all of your stuff
element.css('pointer-events', 'auto');
};
After hours of searching i fixed it in this way:
old_timestamp = null;
$('#productivity_table').on('click', function(event) {
// code executed at first load
// not working if you press too many clicks, it waits 1 second
if(old_timestamp == null || old_timestamp + 1000 < event.timeStamp)
{
// write the code / slide / fade / whatever
old_timestamp = event.timeStamp;
}
});
you can use jQuery's [one][1] :
.one( events [, data ], handler ) Returns: jQuery
Description: Attach a handler to an event for the elements. The handler is executed at most once per element per event type.
see examples:
using jQuery: https://codepen.io/loicjaouen/pen/RwweLVx
// add an even listener that will run only once
$("#click_here_button").one("click", once_callback);
using count,
clickcount++;
if (clickcount == 1) {}
After coming back again clickcount set to zero.
May be this will help and give the desired functionality :
$('#disable').on('click', function(){
$('#disable').attr("disabled", true);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="disable">Disable Me!</button>
<p>Hello</p>
We can use on and off click for preventing Multiple clicks. i tried it to my application and it's working as expected.
$(document).ready(function () {
$("#disable").on('click', function () {
$(this).off('click');
// enter code here
});
})
This should work for you:
$(document).ready(function () {
$('.applicationButton').click(function (e) {
var btn = $(this),
isPageValid = Page_ClientValidate(); // cache state of page validation
if (!isPageValid) {
// page isn't valid, block form submission
e.preventDefault();
}
// disable the button only if the page is valid.
// when the postback returns, the button will be re-enabled by default
btn.prop('disabled', isPageValid);
return isPageValid;
});
});
Please note that you should also take steps server-side to prevent double-posts as not every visitor to your site will be polite enough to visit it with a browser (let alone a JavaScript-enabled browser).
The absolute best way I've found is to immediately disable the button when clicked:
$('#myButton').click(function() {
$('#myButton').prop('disabled', true);
});
And re-enable it when needed, for example:
validation failed
error while processing the form data by the server, then after an error response using jQuery
Another way to avoid a quick double-click is to use the native JavaScript function ondblclick, but in this case it doesn't work if the submit form works through jQuery.
One way you do this is set a counter and if number exceeds the certain number return false.
easy as this.
var mybutton_counter=0;
$("#mybutton").on('click', function(e){
if (mybutton_counter>0){return false;} //you can set the number to any
//your call
mybutton_counter++; //incremental
});
make sure, if statement is on top of your call.
If you are doing a full round-trip post-back, you can just make the button disappear. If there are validation errors, the button will be visible again upon reload of the page.
First set add a style to your button:
<h:commandButton id="SaveBtn" value="Save"
styleClass="hideOnClick"
actionListener="#{someBean.saveAction()}"/>
Then make it hide when clicked.
$(document).ready(function() {
$(".hideOnClick").click(function(e) {
$(e.toElement).hide();
});
});
Just copy paste this code in your script and edit #button1 with your button id and it will resolve your issue.
<script type="text/javascript">
$(document).ready(function(){
$("#button1").submit(function() {
$(this).submit(function() {
return false;
});
return true;
});
});
</script
Plain JavaScript:
Set an attribute to the element being interacted
Remove the attribute after a timeout
If the element has the attribute, do nothing
const throttleInput = document.querySelector('button');
throttleInput.onclick = function() {
if (!throttleInput.hasAttribute('data-prevent-double-click')) {
throttleInput.setAttribute('data-prevent-double-click', true);
throttleInput.setAttribute('disabled', true);
document.body.append("Foo!");
}
setTimeout(function() {
throttleInput.removeAttribute('disabled');
throttleInput.removeAttribute('data-prevent-double-click');
}, 3000);
}
<button>Click to add "Foo"!</button>
We also set the button to .disabled=true. I added the HTML Command input with type hidden to identify if the transaction has been added by the Computer Server to the Database.
Example HTML and PHP Commands:
<button onclick="myAddFunction(<?php echo $value['patient_id'];?>)" id="addButtonId">ADD</button>
<input type="hidden" id="hasPatientInListParam" value="<?php echo $hasPatientInListParamValue;?>">
Example Javascript Command:
function myAddFunction(patientId) {
document.getElementById("addButtonId").disabled=true;
var hasPatientInList = document.getElementById("hasPatientInListParam").value;
if (hasPatientInList) {
alert("Only one (1) patient in each List.");
return;
}
window.location.href = "webAddress/addTransaction/"+patientId; //reloads page
}
After reloading the page, the computer auto-sets the button to .disabled=false. At present, these actions prevent the multiple clicks problem in our case.
I hope these help you too.
Thank you.
One way I found that works is using bootstrap css to display a modal window with a spinner on it. This way nothing in the background can be clicked. Just need to make sure that you hide the modal window again after your long process completes.
so I found a simple solution, hope this helps.
all I had to do was create a counter = 0, and make the function that runs when clicked only runnable if the counter is = 0, when someone clicks the function the first line in the function sets counter = 1 and this will prevent the user from running the function multiple times when the function is done the last line of the code inside the function sets counter to 0 again
you could use a structure like this, it will execute just once:
document.getElementById('buttonID').addEventListener('click', () => {
...Do things...
},{once:true});

After Input goes Invalid in HTML5 set error message and prevent default error message from kendo in a grid

I stuck with the inline validation in the kendo grid.
I don't want to validate after losing focus. I want to validate immediately after typing. So I start using the HTML validator. It works pretty well but the problem is I cant answer these two questions:
which event set the input from valid to invalid.
which event displays the error message.
My Current work: https://dojo.telerik.com/OSONo/56
which event set the input from valid to invalid.
...
which event displays the error message.
Just run your kendoValidator with validator.validate();
The error messages are also set with validate().
Something like this should work:
$(document).on('input propertychange', function() {
validator.validate();
});
The warning seems to be hidden behind some elements, so you can also add the folowing errorTemplate to your kendoValidator:
errorTemplate: '<div class="k-widget k-tooltip k-tooltip-validation" style="margin: 0.5em; display: block;"><span class="k-icon k-i-warning"></span>#=message#<div class="k-callout k-callout-n"></div></div>'
And the whole solution:
https://dojo.telerik.com/OSONo/66
Solved my Problem on my Own. I will edit the post so you can see what i mean but first i just give the dojo projcet.
https://dojo.telerik.com/OSONo/64
my edit:
I am sorry for my previous anwser, i just want to give him my solution i mention in my comment.
In my solution i created an event listener, how listen to all input elements. When something has changed it, saves the current cursor position (its import for ie support) and after this it trigger my "change" event. The "change" event check if it is valid or invalid. If it is invalid the kendo validator shows imidently the error-message (not as default by a blur event).
var ValidierungCheckClass = (function () {
return {
AllDOMElements: function () {
$('body').on('input', function () {
var myActiveElement = $(':focus');
if ((myActiveElement) && (myActiveElement.context.activeElement.nodeName.toLowerCase() !== "body")) {
var myActiveDOMElement = myActiveElement[0],
start = myActiveDOMElement.selectionStart, //just for IE Support
end = myActiveDOMElement.selectionEnd; //just for IE Support
myActiveElement.trigger("change");
myActiveDOMElement.setSelectionRange(start, end); //just for IE Support
}
})
}
}
});
The change event is allready created from kendo so you dont have to write your own.
At least you have to call the method when creating the website.
<script>
ValidierungCheckClass().AllDOMElements();
</script>
This is my Solution to my problem.
best regards.

Should the window.statechange be triggered when I navigate back from an external link?

I'm using History.js (the jquery.history.js v1.8b2). Chrome version 30.0.1599.101 m.
I can't figure out how to make History.js work the way I'd expect.
I have a page that has two links. The first simulates an ajax operation. It just changes the text in an <h2> in the page from "start" to "2". The second link just points to google.com.
Here's what I do:
Clear cache in chrome
Load the page
Click the first link (I call pushState, statechange occurs and there I update my text to "2")
Click the google.com link (goes to google)
Click the browser Back button.
Upon back button click, I expect that the statechange handler should be called and I would then get my state object so I could restore the text to "2".
But the handler is not called. So my page is left with text "start" (the cached page in the browser). Interestingly, the url is set to the "2" version that I pushed in my pushState call.
Am I missing something? Here is my code:
<h2 id="state">start</h2>
<a id="2" class="button" href="#">Goto State 2</a>
Goto google
<script type="text/javascript">
$(function() {
History.Adapter.bind(window, "statechange", function() {
console.log("statechange called");
var state = History.getState();
if (state.data.mystate) {
// Restore the old state
$("#state").text(state.data.mystate);
} else {
// Start state
$("#state").text("start");
}
});
$(".button").click(function(e) {
// push the state we're transitioning to
var newState = $(this).attr("id");
History.pushState(
{ mystate: newState },
"at state " + newState,
"http://localhost:50494/PushState?state=" + newState);
// statechange will be called now, and we'll update the page from our newState
e.preventDefault();
});
});
</script>
I think the answer is no, the statechange isn't supposed to be called when navigating back from outside the page.
I noticed that the demo at http://browserstate.github.com/history.js/demo/ was working as I'd expect, so I did a view source to see how it was working. From what I can tell, here is how you are supposed to use History.js.
When your page loads, you look at History.getState().data. If you recognize one of your states there, then it means you are navigating back into your page from a different page, like from an external link you went to. (Note: the browser may have just loaded your page from cache or it could have been reloaded from the server. Shouldn't matter because you're going to update the page/ui with the state you just found). So, update your page to that state. If you didn't recognize the state, then it's a first time load as far as your page is concerned. Init appropriately.
The statechange event will get called upon the browser back/forward button between "ajax" states within your page (states you've pushed while in this one page). It will also get called when you call pushState(). Huh, isn't that confusing? Yes, so when you want to transition to a new state within your page, follow this pattern:
Prepare your state object (could involve an ajax call),
Call pushState(yourObject,...)
Don't update your page/ui yet.
You actually update your page/ui from the statechanged handler that's gonna get called in a moment.
I mistakenly thought you were supposed to do all the work of updating the page, then push the state afterward. This will just make things hard, since statechanged is gonna get called too.
Also, it appears that in general, you should push states for ajax-like transitions within the one page you're on. Don't push states for links you follow outside the page (unless you really understand all this and are trying to do something fancy).
I've updated the sample code here to show what's working for me now:
<h2 id="state">start</h2>
<a id="2" class="button" href="#">Goto State 2</a>
Goto google
<script type="text/javascript">
$(function () {
// page loading, check for available state I recognize
var availableState = History.getState();
if (!availableState.data.mystate) {
// loading for the first time
$("#state").text("start");
} else {
// load from the available state
loadState(availableState);
}
History.Adapter.bind(window, "statechange", function () {
var state = History.getState();
loadState(state);
});
function loadState(state) {
if (state.data.mystate) {
// update the page to this state
$("#state").text(state.data.mystate);
} else {
// update the page to the initial state
$("#state").text("start");
}
}
$(".button").click(function (e) {
// The user clicked a button, so we want to transition to a new state
// in this page. Push the state we're transitioning to (which we've hidden
// in the id attribute in this example).
var newState = $(this).attr("id");
History.pushState(
{ mystate: newState },
"at state " + newState, // title
"?state=" + newState); // url
// statechange will be called now, and we'll update the page from our newState
e.preventDefault();
});
});
</script>