Is it possible to click page element in casper js without passing selector? I mean I can't do that:
casperjs.thenClick('#test');
But I have
var testV = document.querySelector('#test');
And I want do something like this:
casperjs.thenClick(testV);
For now it doesn't work
You are using thenClick improperly. Make sure the then.click is not contained within a casper.evaluate block and note there is not the js on the end of casper. It should be implemented as:
casper.thenClick('a', function() {
this.echo("I clicked on first link found, the page is now loaded.");
});
If you want to just perform a regular click on selector you can do the following:
casper.then(function() {
// Click on 1st result link
this.click('h3.r a');
});
If you would like to use javascript, make sure you are within a casper.evaluate statement. You can use the following:
casper.then(function() {
casper.evaluate(function() {
var testV = document.getElementById("test");
testV.click();
});
});
Related
so I have this <a> tag:
<a href="/book-testdrive" class="addtocart" value="YX57WDL" title="Book Test Drive">
<i class="glyphicon glyphicon-road"></i>
<span> Book Test Drive</span>
</a>
As you can see it is given a value of value="YX57WDL" now what I would like to do is capture that value when the a tag is clicked and placed into a variable.
There are many <a> tags on my page with many different values that are created dynamically. If a user presses another a tag I'd like it storing in the same variable but replace the value with that of the unique <a> tag value.
Also the variable needs to be stored site wide, I guess the solution to this would be Web Storage API.
So far I've tried using this Javascript:
var links = document.querySelectorAll('.addtocart ');
links.onclick = function(){
localstorage['storedValue'] = this.value ;
}
However when I console.log() the links variable it contains nothing.
Any idea why this might be happening?
Thanks
The problem is that document.querySelectorAll returns a (non-live) node list. This means that it is basically an array, so you could do a loop for each one instead:
for (var i = 0; i < links.length; i++) {
links[i].onclick = function(){
localStorage['storedValue'] = this.value ;
}
}
Also note that I changed localstorage to localStorage because it's case sensitive.
You will need to wait until the DOM is loaded, or else the call to document.querySelectorAll() will not find anything if the element you are looking for has not been added to the DOM yet.
I see you added jquery as a tag, so I assume you are using jquery. If that is the case, you can wrap your code with the jquery function to wait for the DOM to be ready, like this:
$(document).ready(function() {
var links = document.querySelectorAll('.addtocart ');
links.onclick = function(){
localStorage['storedValue'] = this.value ;
}
});
Also if you are using jquery, you could be using its on function to make this a lot simpler.
$(document).ready(function() {
$('.addtocart').on('click', function() {
localStorage['storedValue'] = this.value;
}
});
If you are not using jquery, see this question about how to wait for the DOM to load without the jquery $(document).ready() function.
Try ".getAttribute('value')" instead of ".value":
var links = document.querySelector('a.addtocart');
links.onclick = function(){
localStorage['storedValue'] = links.getAttribute('value');
}
Since you are using jQuery, you can do something like this:
$("body").on("click", ".addtocart", function(e) {
localstorage['storedValue'] = $(this).val();
});
You surely wonder why did your attempt fail. In fact, you were not too far from the solution, but you probably ran your script before your links were created. With the .on() function of jQuery you have a listener to the current and future elements matching the selector (which is ".addtocart").
I have a link that is generated by a core module (meaning I can't modify the code) as such:
<a id="my-unique-id-1" class="my-link-class" href="/switch off">Switch off</a>
Problem is, the ID and class are within the <a> tag and I do not have any useable elements wrapped around the link that I can use.
When clicked, it goes and do what it has to do server side (see code following), and then returns this:
<a id="my-unique-id-1" class="my-link-class it-is-off" href="/switch on">Switch on</a>
I want to replace or amend the complete first link.
First the jQuery script:
$(".my-link-class").click(function() {
var current_id = $(this).attr('id');
var link = $(this).attr('href');
$.ajax({url: link, success: function (result) {
//All works fine up to here. The changes are made in server side and returns the new link as the result.
//Following is my problem:
if(result){
$(current_id).replaceWith(result); //the selector is wrong, I know.
}
}
}
My problem is that the id (current_id) is already within a <a> tag.
How can I refer to the selector in the tag.
I tried:
$(current_id).replaceWith(result); //nothing happens
$('#' + current_id).replaceWith(result);
$('a#' + current_id).replaceWith(result);
But I get with the last two TypeError: Argument 1 of Node.appendChild does not implement interface Node.
(I know I can do other things than replaceWith such as changing text and href in link, but the problem here is to find the selector first).
You can just use $(this).replaceWith():
$(document).on('click', '.my-link-class', function() {
var html = '<a id="my-unique-id-1" class="my-link-class it-is-off" href="/switch on">Switch on</a>';
$(this).replaceWith(html);
return false;
});
.it-is-off {
color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a id="my-unique-id-1" class="my-link-class" href="/switch off">Switch off</a>
I think there are two things happening here.
You are trying to use an ID to replace an element, when it would be easier to just keep a reference to the DOM element you want to replace rather than finding it twice.
You are binding an event to an anchor tag that you are then trying to replace. Once you replace it, the event will go away. The way to avoid this issue is bind your event to something that won't be changing. That can be the element right above the one you are going to replace, or it can be a much higher up element like the body element.
Here's a possible solution that fixes both problems. I've written a function called simulatedAjax to give an idea of what I think you're saying the backend code is doing. It follows the same idea as the jQuery $.get using the configurationObject, callback(result) signature.
function simulatedAjax(config, done){
var onOffText = (config.url === "on" ? "off" : "on");
done('Switch '+ onOffText +'');
}
And now your client code
$(function(){
// Bind the click to the body element, but with a delegate to your link class .custom-link
$('body').on('click', '.custom-link', function(e){
// Store a reference to the A tag, name is irrelevant but self is easy to understand
var self = this;
// Keep the page from actually navigating to the href
e.preventDefault();
//Replace with real jQuery $.get or $.ajax with configuration
simulatedAjax({
url: $(this).attr('href')
}, function(resultHTML){
// Since we stored a reference to the original in the self variable, we can just replace it here. Note that if we tried to use `this` here, it wouldn't refer to the right `this`
$(self).replaceWith(resultHTML);
});
});
});
You can see this code sample working in this JSFiddle http://jsfiddle.net/x83vfmuw/
Hope this helps!
I am currently learning JavaScript using O'Reilly's "Learning Web Application Development". In the example, we are constructing a website using HTML and CSS, which includes 3 tabs which should be able to be selected and become the "active" tab. The books claims that the following two ways of writing the tab code are equivalent:
1)
var main = function() {
"use strict";
var tabNumber;
for (tabNumber=1;tabNumber<=3;tabNumber++) {
var tabSelector = ".tabs a:nth-child("+tabNumber+") span";
$(tabSelector).on("click",function() {
$(".tabs span").removeClass("active");
$(tabSelector).addClass("active");
$("main .content").empty();
return false;
});
}
}
$(document).ready(main);
2)
var main = function() {
"use strict";
$(".tabs a span").toArray().forEach(function(element) {
$(element).on("click", function() {
console.print("this element: " + element);
$(".tabs span").removeClass("active");
$(element).addClass("active");
$("main .content").empty();
return false;
});
});
}
$(document).ready(main);
However, they do not output the same result. The version using forEach works correctly, so that when I click one of the tabs the attention moves to that tab and it becomes highlighted. However, in the version using a for loop, whenever I click any tab, the attention always moves to the last tab. To confirm what is happening, I printed out the name of the element inside the event listener with both methods, using 3 tabs total. And using the for loop, no matter which tab I click I am getting a response of
"this element: .tabs a:nth-child(3) span"
Could someone please help me explain why this is happening? Why is the output different using for or forEach? And why, using for, is it always passing the last element of tabs to the event listener?
Looks like there's a problem here:
var tabSelector = ".tabs a:nth-child("+tabNumber+") span";
$tabSelector.on("click",function(){
You've created a variable that doesn't have the $ at the beginning, then attached the event to a variable (not sure what it would refer to) with a $ at the beginning.
It should be changed to this, I believe:
$(tabSelector).on("click",function(){
In the for loop solution, you are setting tabSelector multiple times like so:
var tabSelector = ".tabs a:nth-child("+tabNumber+") span";
This selector is, in the end, going to be set to the last tabNumber, which is always going to be called when you make a reference to it:
$(tabSelector).addClass("active");
To avoid that, replace it by this, which will be different for each of them:
$(this).addClass("active");
JS Fiddle Demo
I'm trying to make a button that will hide a specific -- and then replace it with another hidden . However, when I test the code, everything fires correctly except for the .removeClass which contains the "display: none."
Here is the code:
<script type="text/javascript">
$(document).ready(function(){
var webform = document.getElementById('block-webform-client-block-18');
var unmarriedbutton = document.getElementById('unmarried');
var buyingblock = document.getElementById('block-block-10');
$(unmarriedbutton).click(function () {
$(buyingblock).fadeOut('slow', function() {
$(this).replaceWith(function () {
$(webform).removeClass('hiddenbox')
});
});
});
});
</script>
The CSS on 'hiddenbox' is nothing more than "display: none.'
There is a with the id of unmarried, which when clicked fades out a div and replaces it with a hidden div that removes the class to reveal it. However, the last part doesn't fire -- everything else does and functions properly. When I look at in the console too, it shows no errors.
Can someone please tell me where the error is? Thanks!
Edit: I may be using the wrong function to replace the div with, so here's the site: http://drjohncurtis.com/happily-un-married. If you click the "download the book" button, the the div disappears and is replaced correctly with the div#block-webform-client-block-18. However, it remains hidden.
The function you pass to replaceWith has to return the content you want to replace it with. You have to actually return the content.
I don't know exactly what you're trying to accomplish, but you could use this if the goal is to replace it with the webform object:
$(this).replaceWith(function () {
return($(webform).removeClass('hiddenbox'));
});
NB, use jquery !
var webform = $('#block-webform-client-block-18');
var unmarriedbutton = $('#unmarried');
var buyingblock =$('#block-block-10');
unmarriedbutton.click(function () {
buyingblock.fadeOut('slow', function() {
$(this).replaceWith( webform.removeClass('hiddenbox'));
});
});
Was too fast, i believe it's the way you select your object (getelementbyid) then you create a jquery object from it... -> use jquery API
I'm trying to use Phantom.JS to do some page automation on this page: https://reserve.apple.com/GB/en_GB/reserve/iPhone
I know how to use document.getElementById('store') = "R363" to choose the first option. But it seems after I've chosen the first option, the DOM element of the original page will change and I don't know how to achieve that using Phantom.JS
Instead of using document.getElementById('store') = "R363" try using jQuery instead like so:
var page = require('webpage').create();
// open the page
page.open('https://reserve.apple.com/GB/en_GB/reserve/iPhone', function() {
//inject jQuery
page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
// run the following code in the context of the page
page.evaluate(function() {
// change the value of the combobox
$("#store").val( newval );
// do stuff in the page
});
phantom.exit()
});
});