Puppeteer: Clicking button on a website doesn't work - forms

I'm trying to find the corresponding code for puppeteer to automate a button press.
In a userscript it can be done easily via
document.getElementsByClassName("details-cart-button btn btn-primary btn-block btn-lg d-flex justify-content-center tp-button ")[0].click();
However im struggling to replicate the same behavior using puppeteer.
What I tried so far:
//Try 1:
await page.click('a[class="details-cart-button btn btn-primary btn-block btn-lg d-flex justify-content-center tp-button "]');
//Try 2:
await page.$eval('a[class^="details-cart-button"]', el => el.click());
//Try3:
const form = await page.$('id#add-to-cart-form');
await form.evaluate( form => form.click() );
//Try4:
await Promise.all([
await page.click('#add-to-cart-form > a.details-cart-button.btn.btn-primary.btn-block.btn-lg.d-flex.justify-content-center.tp-button')
]);
None of the methods seem to work sadly and I have no idea how to get it done.
Could someone be kind enough to point me in the right direction?
Thanks a lot in advance!

The below code should work.
const puppeteer = require('puppeteer');
(async ()=>{
const browser = await puppeteer.launch({headless:false});
const [page] = await browser.pages();
await page.goto('https://www.alternate.de/html/product/1685585');
const acceptCookiesSelector='button[class="cookie-submit-all"]';
await page.waitForSelector(acceptCookiesSelector);
await page.click(acceptCookiesSelector);
const buySelector='a[class="details-cart-button btn btn-primary btn-block btn-lg d-flex justify-content-center tp-button "]';
await page.waitForSelector(buySelector);
await page.click(buySelector);
})();
I will try to explain why your code didn't work.
The click method that you use on the page scrolls into view the element that you want to click and uses the left mouse button and clicks on it, in your case, the button was in the view, but it was overshadowed by the accept-cookie banner, so all you have to do is click on accept the cookies to get rid of that banner then click on the buy button and it will work.
Your first example worked because click method in the browser console is a different method than the one used on Puppeteer, and it worked because it doesn't rely on the mouse to generate the click.

Related

Ionic progress bar still appears as a spinner

I am implementing loading as shown below. When I run the application on my iOS, the loading still shows as a spinner instead of a progress bar. Why is this happening in my app?
List.ts
async presentLoadingDefault() {
this.loading = await this.loadCtrl.create({
content: '<ion-progress-bar value="0.5"></ion-progress-bar>'
});
await this.loading.present();
}
async dismissLoader()
{
await this.loading.dismiss();
}
I'm afraid ionic 3 doesn't support ion-progress-bar component.
It is formally supported by ionic 4. Refer here.
In order to implement progress-bar in ionic 3, please follow this stackblitz tutorial.
progress-bar.html
<div class="progress-outer">
<div class="progress-inner" [style.width]="progress + '%'">
{{progress}}%
</div>
</div>

Unable to use debounceTime on ion-button click event

Currently I am having an ion-button with click event which calls a method.
<ion-button expand="full" color="primary" (click)="sendMsg()">Tap</ion-button>
sendMsg method contains the statements to push the objects to an array and opens modal on some condition.
sendMsg = () =>{
// statements to push an objects to an array(this is an array displays on chat page);
this.openModal();
}
async openModal() {
const myModal = await this.modalController.create({
component: ModalPage,
componentProps: {
firstAction: this.firstAction,
secondAction: this.secondAction,
thirdAction: this.thirdAction
},
cssClass: 'modal-css',
backdropDismiss: false
});
It's a chat page where we get the messages on click of TAP button and while tapping in between we show an ion modal . The issue here is when we tap super fast and modal comes up in one of the click event and since we are clicking fast I could see the messages displaying which are suppose to display after the modal comes up..
To avoid this , I thought of adding debounceTime which can have some time delay and considers the latest click event and this was working in normal angular world.
I have followed https://coryrylan.com/blog/creating-a-custom-debounce-click-directive-in-angular but it didn't work under ionic..
Any thoughts are really appreciated..
use a subject as event emitting source and control the click rate from there
const openModalAction=new Subject()
sendMsg = () =>{
// statements to push an objects to an array(this is an array displays on chat page);
openModalAction.next()
}
const openModal=defer(()=>from(this.modalController.create({
component: ModalPage,
componentProps: {
firstAction: this.firstAction,
secondAction: this.secondAction,
thirdAction: this.thirdAction
},
cssClass: 'modal-css',
backdropDismiss: false
})))
const openModalAction.pipe(dounceTime(1000),switchMap(_=>openModal)

AngularJS and Tab Order (Disabled Buttons)

I have a form, and I'm navigating only with TAB. Tab order should be input > select > button, but because of the ng-disable on the SUBMIT, on certain browsers the TAB out of the select will kick you somewhere else.
HTML
<div ng-app="myApp">
<div ng-controller="FirstCtrl">
<form name="myForm" ng-submit="submit()" novalidate>
First Name: <input type="text" ng-model="Data.FirstName" required><br>
Last Name: <select ng-model="Data.LastName" required>
<option value="Bigglesworth">Bigglesworth</option>
<option value="Burgermeister">Burgermeister</option>
</select><br>
<input type="submit" value="Submit" ng-disabled="myForm.$invalid" />
</form>
</div>
</div>
JS
var myApp = angular.module('myApp', []);
myApp.factory('Data', function(){
return {
FirstName: '',
LastName: ''
};
});
myApp.controller('FirstCtrl', function( $scope, Data ){
$scope.Data = Data;
$scope.submit = function() {
console.log('you just submitted, foolio');
}
});
JsFiddle here.
On Mac FF the final tab kicks you to the address bar before enabling the submit button. Mac Chrome works as you'd expect, focusing on the submit button after final tab. I know Windows is janky, but don't have exact specs to post.
Thoughts? How can I do this in a fool-proof fashion?
EDIT
I've selected #David B.'s answer as it's the best Angular solution. I ended up using a somewhat hidden element right after the the submit button so the focus would stay in the same general area. Lame and hacky, I know, but for a tight deadline it worked.
<h3><button class="fakebtn_hack">Confirmation</button></h3>
<style>.fakebtn_hack {background:none; border:none; color: #FF6319; cursor: default; font-size: 1em; padding: 0;}</style>
This happens because Firefox doesn't send a change event on key-driven changes of the select. Angular doesn't see the change until the tab is hit, so the submit button isn't enabled until after the tab has been processed by the browser (and focus sent to some other element, e.g., the address bar). The W3C standard suggests not sending the event until the control loses focus, although Chrome sends one for any change and Firefox does if the change was mouse-driven.
See the angularjs issue tracker for more: https://github.com/angular/angular.js/issues/4216
As suggested in the issue tracker, solve it by manually issuing the change event via the following select directive (http://jsfiddle.net/j5ZzE/):
myApp.directive("select", function () {
return {
restrict: "E",
require: "?ngModel",
scope: false,
link: function (scope, element, attrs, ngModel) {
if (!ngModel) {
return;
}
element.bind("keyup", function () {
element.trigger("change");
})
}
}
})
You'll need JQuery loaded before AngularJS to have the trigger function available on the element object.
Manually include an empty option (<option value=""></option>) in your select or the first option will be auto-selected when the control receives focus.
Unlike the default behavior, this empty option will not disappear after selecting a real option. I suppose you could remove the empty option by declaring all the options via ng-options or ng-repeat and then removing the empty one from the bound scope once a real option has been selected, but I've never tried it.

jQuery Stop .blur() event when clicking "submit" button

I am building a small landing page with a simple demo e-mail signup form. I want to have the form field open up when focused, and then shrink back down on blur.
However the problem I'm facing is when you click the submit button this instigates the blur function, hiding the button and shrinking the form. I need to find a way to stop the .blur() method only when the user is clicking to focus on the submit button. Is there any good workaround for this?
Would appreciate any help I can get!
I know this question is old but the simplest way to do it would be to check event.relatedTarget. The first part of the if statement is to prevent throwing an error if relatedTarget is null (the IF will short circuit because null is equivalent to false and the browser knows that it doesn't have to check the second condition if the first condition is false in an && statement).
So:
if(event.relatedTarget && event.relatedTarget.type!="submit"){
//do your animation
}
It isn't the prettiest solution, but it does work. Try this:
$("#submitbtn").mousedown(function() {
mousedownHappened = true;
});
$("#email").blur(function() {
if (mousedownHappened) // cancel the blur event
{
mousedownHappened = false;
}
else // blur event is okay
{
$("#email").animate({
opacity: 0.75,
width: '-=240px'
}, 500, function() {
});
// hide submit button
$("#submitbtn").fadeOut(400);
}
});​
DEMO HERE
Try this inside .blur handler:
if ($(':focus').is('#submitbtn')) { return false; }
why not rely on submit event instead of click? http://jsbin.com/ehujup/5/edit
just couple changes into the html and js
wrap inputs into the form and add required for email as it obviously suppose to be
<form id="form">
<div id="signup">
<input type="email" name="email" id="email" placeholder="me#email.com" tabindex="1" required="required">
<input type="submit" name="submit" id="submitbtn" value="Signup" class="submit-btn" tabindex="2">
</div>
</form>
in js, remove handler which listen #submitbtn
$("#submitbtn").on("click", function(e){
e.stopImmediatePropagation();
$("#signup").fadeOut(220);
});
and use instead submit form listerer
$("#form").on("submit", function(e){
$("#signup").fadeOut(220);
return false;
});
you may use $.ajax() to make it even better.
Doing this you gain point in terms of validation and the native browser's HTML5 validator will make check email format where it is supported.

How to call autocomplete select event from outside the function

I have a location search form that uses jQuery UI autocomplete.
When the user starts typing into the input, our list of locations appear as a drop down menu just below the input. If the user clicks one of the locations, the page redirects to the landing page for that location. The user can also click "enter" on the keyboard instead of explicitly clicking on the item.
Here's the probelm. I can't figure out how to get autocomplete to work if the user clicks the SUBMIT button. I'm not allowed to simply remove the submit button because it's a "call to action". The markup & code look like this: (I'm writing this from memory, so it may not be exact)
<form id="locationSearch">
<input type="text" id="enterLocation" />
<input id="goButton "type="submit" value="GO" />
</form>
<script>
var locations = [<br />
{'value': 'Brooklyn', 'url': '/ny/brooklyn/browse'}
{ 'value' : 'Hoboken; , 'url' : /nj/hoboken/browse'}
];
$('#enterLocation').autocomplete({
autoFocus: true,
source: 'locations',
select: event, ui (function() {
window.location.url
});
});
</script>
What I need to do is something like this:
$('#goButton').click(function() {
// trigger automcomplete select
});
Any suggestions are greatly appreciated!
Try using
$('#enterLocation').trigger("autocompleteselect", function(){});