Phantom.js stuck on choosing next element - javascript

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

Related

JavaScript only being called once in Squarespace

I have some custom JavaScript on my SquareSpace site that manipulates Product titles beyond what you can do with SquareSpace's default style editor. It works when initially loading the page (https://www.manilva.co/catalogue-accessories/) but if you click on any of the categories on the left, the styling resets to the default.
I'm assuming the JavaScript is being overwritten by the SquareSpace style, but I can't figure out why. Perhaps I'm calling the function in the wrong place?
Any suggestions would be helpful.
Thanks!
Current code:
document.querySelectorAll(".ProductList-filter-list-item-link".forEach(i=>i.addEventListener("click", function()
{
var prodList = document.querySelectorAll("h1.ProductList-title");
for (i = 0, len = prodList.length; i < len; i++)
{
var text = prodList[i].innerText;
var index = text.indexOf('-');
var lower = text.substring(0, index);
var higher = text.substring(index + 2);
prodList[i].innerHTML = lower.bold() + "<br>" + higher;
});
The source of your problem is that your template has AJAX loading enabled. There are currently a couple generally-accepted ways to deal with this as a Squarespace developer:
Disable AJAX loading
Write your javascript functions in a
manner that will run on initial site load and whenever an "AJAX load" takes place.
Option 1 - Disable AJAX:
In the Home Menu, click Design, and then click Site Styles.
Scroll down to Site: Loading.
Uncheck Enable Ajax Loading.
Option 2 - Account for AJAX in Your JS
There are a number of ways that developers approach this, including the following, added via sitewide code injection:
<script>
window.Squarespace.onInitialize(Y, function() {
// do stuff
});
</script>
or
<script>
(function() {
// Establish a function that does stuff.
var myFunction = function() {
// Do stuff here.
};
// Initialize the fn on site load.
myFunction();
// myFunction2(); , etc...
// Reinit. the fn on each new AJAX-loaded page.
window.addEventListener("mercury:load", myFunction);
})();
</script>
or
<script>
(function() {
// Establish a function that does stuff.
var myFunction = function() {
// Do stuff here.
};
// Initialize the fn on site load.
myFunction();
// Reinit. the fn on each new AJAX-loaded page.
new MutationObserver(function() {
myFunction();
// myFunction2(); , etc...
}).observe(document.body, {attributes:true, attributeFilter:["id"]});
})();
</script>
Each of those works for most of the latest (at time of writing) templates most of the time. Each of those have their advantages and disadvantages, and contexts where they do not work as one might expect (for example, on the /cart/ page or other "system" pages). By adding your code within the context of one of the methods above, and ensuring that the code is of course working in the desired contexts and without its own bugs/issues, you will have your code run on initial site load and on each AJAX page load (with some exceptions, depending on the method you use).
Your problem is the page does not reload when clicking a button on the left, just some elements are removed, added and replaced. The changed elements will not be restyled. You will need to re-run your JavaScript after one of those buttons is clicked. Perhaps something like this:
document.querySelectorAll(
".ProductList-filter-list-item"
).forEach(
i=>i.addEventListener(
"click", ()=>console.log("hello")
)
)
where you replace console.log("hello") with whatever resets your formatting.

jQuery keep selected content on load

I'm working on a control panel, and I need to have the output of a command appear live. I have managed to get this to work by having the command output to a file, and loading that file via jQuery. I refresh the output every second using:
<script>
$(function(){
setInterval(refreshFrame, 1000);
});
</script>
and
<script>
document.getElementById("title").innerHTML="Update";
function refreshFrame(){
$("#frame").load("/assets/readfile.php?type=custom#content")
}
</script>
This works and loads the output without refreshing the entire page. However this makes copying impossible as the selection is gone or gets mutated as the contents are loaded again. Is there any way to keep the selection across reloads, and if not, how can I pause the refreshing when there is a selection?
try something like this:
$(function(){
document.getElementById("title").innerHTML="Update";
setInterval(function(){
if(!$('#frame').is(":hover")){
$("#frame").load("/assets/readfile.php?type=custom#content")
}
}, 1000);
});
How about only updating the element's html if the content has changed and the user has not selected anything in #frame?
var lastContent;
$(function(){
setInterval(refreshFrame, 1000);
});
function refreshFrame(){
$.ajax({
url:"/assets/readfile.php?type=custom#content"
}).done(function(content) {
if(!$(window.getSelection().anchorNode).is("#frame") && $(window.getSelection().anchorNode).closest("#frame").length == 0 && content != lastContent) {
$("#frame").html(content);
lastContent=content;
}
});
}

Update div with jQuery ajax response html Not Posting Back to Page

I've been struggling with this for a few days now and can't figure out why this won't work. I need to update a link on a page with a new file. The post request and new file show in the Google Chrome development network, but the actual page won't update. I have checked other posts and can't figure this out. My understanding is that my code should be updating the div "mapData" with the new link, image, etc. The page response in the development window has the correct html page and I need to take the div portion from it, change it in the html page displayed, and have that page update. Should be simple!
function updatePieFact(){
var scenario = $("#scenario").val();
var year_run = $("#year_run").val();
var actType = $("input:radio[name=actType]:checked").val();
var znType = $("input:radio[name=znType]:checked").val();
var data = {'pieFact': pieFact, 'csrfmiddlewaretoken':'f89lua2QMAt7oz6057PVcahr3EUsSTyI', 'scenario':scenario, 'year_run':year_run, 'actType':actType, 'znType':znType};
$.post(URL, data, function(data){
var result = $('<div />').append(data).find('#mapData').html();
$("#mapData").html(result);
});
}
var pieFact = 1;
$(document).ready(function(){
$('#bttnMinus').click(function(){
pieFact*=0.75;
updatePieFact();
});
$('#bttnPlus').click(function(){
pieFact*=1.25;
updatePieFact();
});
});
Did you mean to do this?
$.post(URL, data, function(result){
var mapDataHtml = $(result).find("#mapData").html();
$("#mapData").html(mapDataHtml);
});
If your buttons are inside of the mapData element, their bindings will be removed when you reload the html. You'll want to use jQuery.on instead of click.
$(document).on('click', '#bttnMinus', function(){
pieFact*=0.75;
updatePieFact();
});
You can use http://api.jquery.com/load/ to simplify it slightly. Your issue might be in how you are setting the html.
$('#mapData').load(URL, data);

casperjs click not selector but variable

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

Initialize media player only if query string parameter is present

I have a SharePoint page that has a hyperlink which points to a video clip. Clicking on the link will play the video in an overlay window (uses Silverlight). If Silverlight runtime is not present, it displays the "install Silverlight" prompt. When the page is invoked with a IsDlg=1 query string, the hyperlink is hidden (it is in the left navigation bar), and only the main content page is shown. But I still get the "install Silverlight" prompt. I want to get rid of the prompt when IsDlg=1 is present.
Below is the relevant javascript code on the page. I've modified it slightly to initialize the media player only if IsDlg=1 is not present. But it is not working as expected. Any ideas?
// original code
$(function () {
mediaPlayer.createOverlayPlayer();
mediaPlayer.attachToMediaLinks(document.getElementById('videoList'), ['wmv', 'avi', 'mp4']);
});
// modified code
$(function () {
var field = 'IsDlg';
var url = window.location.href;
if (url.indexOf('?' + field + '=') != -1) {
} else {
mediaPlayer.createOverlayPlayer();
mediaPlayer.attachToMediaLinks(document.getElementById('videoList'), ['wmv', 'avi', 'mp4']);
}
});
As long as the HTML which embeds the Silverlight control is present, it will show the "Install Silverlight" dialog. If you don't want the dialog to show, you'll have to change the HTML source. You could add JavaScript code to add the HTML dynamically, so that it only shows when necessary. That answer would depend on how you're currently embedding the Silverlight control.
EDIT: You could try code like this:
$(function () {
if (window.location.search.indexOf('IsDlg=1') === -1) {
$.getScript('/_layouts/mediaplayer.js', function () {
mediaPlayer.createOverlayPlayer();
mediaPlayer.attachToMediaLinks(document.getElementById('videoList'), ['wmv', 'avi', 'mp4']);
});
}
});
Your code should work, so you probably want to debug for other possible issues.
$(document).ready(function () { // add explicit wait until dom ready
console.log(window.location.search); // just to check that the parameter is present
if(window.location.search.indexOf("IsDlg=1") < 0){ // testing the query string part only
mediaPlayer.createOverlayPlayer();
mediaPlayer.attachToMediaLinks(document.getElementById('videoList'), ['wmv', 'avi', 'mp4']);
}
});
Try that and see how you get on.

Categories