How to run .evaluate .then multiple times in nightmare - javascript

I tried to scrape web page generated by AJAX. On the web page inside <div class='main'> are several <a class='classLinks'> elements and after click on one of them is being content generated in the same <div class='main'> and <a class='classLinks'> elements are replaced with one <a class='back'> back button.
My task is grab content generated after click on all <a class='classLinks'> elements inside <div class='main'> and write it to console log.
I put all <a class='classLinks'> to the array of selectors but problem is I don't know how to run sequence ".click, .wait, .evaluate., .click" inside for cycle.
Steps are:
goto http://example.com
click on subpage
get all "a" elements
content = ""
for (i=0; i < a.lenght; i++)
{
click on a[i]
content = content + div.innerHTML;
click on "a.back"
}
console.log content;
My code looks:
var content
nightmare
.goto('http://example.com')
.wait('.firstpage')
.click('a.subpage')
.wait('.main')
.evaluate(function(){
var links = document.querySelectorAll('a.classLinks');
for (i = 0; i < links.length; ++i) {
links[i].click();
// now i need to wait for <div class='main'>
.wait('.main')
// and do evaluate again
.evaluate(function(){
//content is glogal variable
content = content + document.querySelector('div.main').innerHTML;
// and click on 'back' link becaus all a.classLinks disappeared
document.querySelector('a.back').click();
})
})
return content;
.end()
.then(function(content) {
console.log(content);
})
Please how to process several evaluations inside for cycle in nightmare?

Related

Change location.href with jQuery

I need to change the location.href of some URLs on my site. These are product cards and they do not contain "a" (which would make this a lot easier).
Here is the HTML:
<div class="product-card " onclick="location.href='https://www.google.com'">
I mean it is pretty simple, but I just cannot get it to work. Did not find any results from Google without this type of results, all of which contain the "a":
$("a[href='http://www.google.com/']").attr('href', 'http://www.live.com/')
Any ideas on how to get this to work with jQuery (or simple JS)?
I cannot change the code itself unfortunaltely, I can just manipulate it with jQuery and JS.
To change the onClick for all the class='product-card', you can do something like this:
// All the links
const links = document.getElementsByClassName('product-card');
// Loop over them
Array.prototype.forEach.call(links, function(el) {
// Set new onClick
el.setAttribute("onClick", "location.href = 'http://www.live.com/'" );
});
<div class="product-card " onclick="location.href='https://www.google.com'">Test</div>
Will produce the following DOM:
<div class="product-card " onclick="location.href = 'http://www.live.com/'">Test</div>
Another option, is to loop over each <div> and check if something like google.com is present in the onClick, if so, we can safely change it without altering any other divs with the same class like so:
// All the divs (or any other element)
const allDivs = document.getElementsByTagName('div');
// For each
Array.from(allDivs).forEach(function(div) {
// If the 'onClick' contains 'google.com', lets change
const oc = div.getAttributeNode('onclick');
if (oc && oc.nodeValue.includes('google.com')) {
// Change onClick
div.setAttribute("onClick", "location.href = 'http://www.live.com/'" );
}
});
<div class="product-card" onclick="location.href='https://www.google.com'">Change me</div>
<div class="product-card">Don't touch me!</div>

Run function on page load (Refresh RSS feed with new URL) Javascript

I have an app where I want to display different RSS feeds on one page, when the corresponding team is clicked.
For example, when I click "Aberdeen" I want the page to show the RSS for Aberdeen.
When I click "Celtic", i want the same page to display the RSS for Celtic.
I will attach my code in one section - basically when the page #feed loads, I need to run the getFeed() function.
I am using jQuery Mobile.
HTML for "feed" page
<div data-role="page" id="feed">
<div data-role="header">
<h1 id="fheader">Header</h1>
</div>
<div data-role="content">
Add to My Teams
<ul data-role="listview" class="list" data-inset="true" >
</ul>
</div>
</div>
Function to getFeed
var feedURL="http://www.football365.com/arsenal/rss";
var n = 12;
function getFeed(url, success, n){
url= feedURL.replace("??", n.toString());
if(window.navigator.onLine) {
$.jGFeed(url, function(feeds) {
// Check for errors
if(!feeds){
// there was an error
return;
} else {
localStorage.setItem(url, JSON.stringify(feeds));
success(feeds.title, feeds.entries);
}
},n );
} else {
// Get the fall-back...
var feed = JSON.parse(localStorage.getItem(url));
if(feed && feed.length > 0) {
success(feed.title, feed.entries);
}
}
}
$(document).on('pagebeforeshow',function(){
getFeed(feedURL,function(title,items){
$("#title").text(title);
for(var index=0; index<items.length; index+=1){
$("#list").append(formatItem(items[index]));
}
$("#list").listview('refresh');
},20);
} );
Function to find RSS URL based on team
function getIndex(teamlist, teamname){
for(var i = 0; i<teamlist.length; i++){
if(teamlist[i].teamname == teamname){
return i; // if found index will return
}
}
return -1; // if not found -1 will return
}
var a = getIndex(teamlist,name); // will give a as 0
console.log(a);
feedURL = teamlist[a].rss_url;
console.log(feedURL);
As you can see, the RSS URL for a specific team is found via index in array. Once it has found the array, it assigns it to the feedURL variable. This part works fine
However, when the page opens, it does not take into consideration the change in variable. I need to refresh or rerun the getFeed() function to take into account the new value of feedURL.
Hope this clears things up :) Thanks :)
If you want to run your function when the page has loaded just use:
$(document).ready(function(){
getFeed();
};
This will run your function when the page has fully rendered and the #feed element is available.

How to implement telephone links with Javascript

I am working with a WordPress theme and this is the functionality that I am trying to achieve:
225-1077
It sure is easily done with HTML but I am really not good with WordPress and this theme I got has so much files in it that it's hard to find where I should edit however, the theme allows you to add custom JS so I was wondering if the functionality above can be done with JS.
Any help is very much appreciated!
Very simply, it is possible, but that doesn't mean it's a good idea. JS support across mobile phones is not consistent, and not even always enabled, which would mean that these people would never see your link.
To create the link with JS is simple :
var cta = document.createElement('a');
cta.href = 'tel:12341234';
cta.setAttribute('class', 'my cta classes');
cta.appendChild(document.createTextNode('1234-1234'));
and then you need to put it somewhere on the page. If we have <div>s all over the place with a specific class, we can use that:
This is our HTML
<div class="target-cta">This div should receive a link</div>
<div class=""> this one shouldn't </div>
<div class="target-cta"> should have one here </div>
<div class=""> ...though not here</div>
<div class="target-cta">and finally, one here:</div>
and our JS to insert the links should loop through these elements, creating the links and inserting them as it goes:
var targets = document.getElementsByClassName('target-cta'),
target,
i,
cta; // Call To Action
for (i = 0; i < targets.length; i++) {
target = targets[i];
cta = document.createElement('a');
cta.href = 'tel:12341234';
cta.setAttribute('class', 'my cta classes');
cta.appendChild(document.createTextNode('1234-1234'));
target.appendChild(cta);
};
var targets = document.getElementsByClassName('target-cta'),
target, i, cta;
for (i = 0; i < targets.length; i++) {
target = targets[i];
cta = document.createElement('a');
cta.href = 'tel:12341234';
cta.setAttribute('class', 'my cta classes');
cta.appendChild(document.createTextNode('1234-1234'));
target.appendChild(cta);
};
<div class="target-cta">This div should receive a link</div>
<div class=""> this one shouldn't </div>
<div class="target-cta"> should have one here </div>
<div class=""> ...though not here</div>
<div class="target-cta">and finally, one here:</div>

Show/Hide Content without reloading the page

I have three content boxes that i want to show and hide using controls.
The HTML is as follows:
<div id="leermat1">
Content here
<a class="pag-next">Next</a>
<a class="pag-prev">Previous</a>
</div>
<div id="leermat2">
Content here
<a class="pag-next">Next</a>
<a class="pag-prev">Previous</a>
</div>
<div id="leermat3">
Content here
<a class="pag-next">Next</a>
<a class="pag-prev">Previous</a>
</div>
I have the two anchors pag-next and pag-prev that will control which of the content divs should be visible at any given point:
I want to write jquery such as, when #leermat1 'pag-next' is clicked, it hides #leermat1 and shows #leermat2. Then when #leermat1 is hidden and #leermat2 shows, when '.pag-next' is clicked, it hides #leermat2, and shows #leermat3.
Also the 'pag-prev' should work the same way.
I started with the following but dont know where to go from here.
$(document).ready(function() {
$('.pag-next').on('click',function() {
$('#leermat1').addClass('hide');
$('#leermat2').addClass('show');
});
});
One more thing is that the '.pag-next' should stop functioning after it has shown #leermat3.
You need this
$('[class^=pag-]').click(function() {
var elem = $('[id^=leermat]').filter(":visible"); // take the visible element
var num = Number(elem[0].id.match(/\d+$/)[0]); // take the number from it
var step = $(this).is('.pag-next') ? 1 : -1; // ternary operator
$('#leermat'+ (num + step)).show(); // show next or back
elem.hide(); // hide the visible element
});
Looks like in your anchor tag you have not given it a class.
Next
You then go on in your JQuery code to add a click function to a class which does not exist.
$('.pag-next').on('click',function()
Try adding class="pag-next" to your anchor tag.
This is what worked for me through a little trial and error. Although I am not sure if this is the most efficient solution.
$('#leermat1 .pag-next').on('click',function(){
$('#leermat1').addClass('hide');
$('#leermat1').removeClass('show');
$('#leermat3').addClass('hide');
$('#leermat3').remove('show');
$('#leermat2').addClass('show');
});
$('#leermat2 .pag-next').on('click',function(){
$('#leermat1').removeClass('show');
$('#leermat2').addClass('hide');
$('#leermat2').removeClass('show');
$('#leermat3').addClass('show');
});
$('#leermat2 .pag-prev').on('click',function(){
$('#leermat2').addClass('hide');
$('#leermat2').removeClass('show');
$('#leermat1').addClass('show');
$('#leermat3').removeClass('show');
});
$('#leermat3 .pag-prev').on('click',function(){
$('#leermat3').addClass('hide');
$('#leermat2').addClass('show');
$('#leermat1').addClass('hide');
$('#leermat3').removeClass('show');
$('#leermat1').removeClass('show');
});

Single page app reload

I am writing a single page app with several divs that have the attribute data-roll="page". Pushing buttons fires ajax queries and the user is redirected to divs down the document like this
<body>
<div data-role="page" id="menu">
//bunch of nav buttons like <a href="#faculty">
</div>
<div data-role="page" id="faculty" data-theme="b">
//dynamicly loaded list of faculty
</div>
and so on.
I want to return to the menu div on refresh but no amount of scrolling
seems to work. Here is my JS with two attempts at getting back to the menu page on page load.
document.ready = init;
function init(){
var button = $('#facultyButton')
,facList = $('#facultyList')
,search = $('#facSearch')
,monikerBox = $('.monikerBox')
,events = $('#events')
,ajaxString = "http://stage.webscope.com/veith/dev/ajax.pl?"
,html = "";
//executed on init
$('html').scrollTop(0);
//events
$(window).on('load',function(){
$('html').scrollTop(0);
});
button.click(function(){
var value = "a";
search.html( "" );
facultyAjax(value);
});
I also tried window.location= menu url (home) in various functions with disastrous results!
Set the window.location you want the user to view with the location object on the load event.
I put this in the html.
<body onload="location.href='#menu'">

Categories

Resources