How to scroll to element using Symfony Panther without executing javascript? - php

I want to scroll to an element using Symfony Panther but without using the javascript method.
Does anybody know a way to do that?
The javascript method is something like this:
<?php
// autoload here
$client = Client::createChromeClient();
$client->executeScript('document.getElementById("someElementId").scrollIntoView();');

Use the client that is the representations of the browser. For instance:
$client = Client::createChromeClient();
$client->getKeyboard()->pressKey(WebDriverKeys::PAGE_DOWN);
of course as you can interact with the mouse or keyboard to scroll down in the browser there are also other possibilities how can you do that. The PageDown is just an example
There are many more interesting functions inside just check the sources

Related

Get pixel coordinates of HTML/DOM elements using PHP

I am working on an web crawler/site analyzer in php. What I need to do is to extract some tags from a HTML file and compute some attributes (such as image size for example). I can easily do this using a DOM parser, but I would also need to find the pixel coordinates and size of a html/DOM tree element (let's say I have a div and I need to know which area it covers and on which coordinate does it start and if). I can define a standard screen resolution, that is not a problem for me, but I need to retrieve the pixel coordinates automatically, by using a server-side php script (or calling some java app from console or something similar, if needed).
From what I understand, I need a headless browser in php and that would simulate/render a webpage, from which I can retrieve the pixel coordinates I need. Would you recommend me a open-source solution for that? Some code snippets would also be useful, so I would not install the solution and then notice it does not provide pixel coordinates.
PS: I see people who answered missed the point of the question, so it means I did not explain well that I need this solution to work COMPLETELY server-side. Say I use a crawler and it feeds html pages to my script. I could launch it from browser, but also from console (like 'php myScript.php').
maybe you can set the coordinates as some kind of metadata inside your tag using javascript
$("element").data("coordinates",""+this.offset.top+","+this.offset.left);
then you have to request with php
$html = file_get_contents($url);
$doc = new DOMDocument();
#$doc->loadHTML($html);
$tags = $doc->getElementsByTagName('element');
foreach ($tags as $tag) {
echo $tag->getAttribute('data'); <-- this will print the coordinates of each tag
}
A Headless browser is an overkill for what you're trying to achieve. Just use cookies to store whatever you want.
So any time you get some piece of information, such as an X,Y coordinate, scroll position, etc. in javascript, simply send it to a PHP script that makes a cookie out of it with some unique string index.
Eventually, you'll have a large array of cookie data that will be directly available to any PHP or javascript file, and you can do anything you'd like with it at that point.
For example, if you wanted to just store stuff in sessions, you could do:
jquery:
// save whatever you want from javascript
// note: probably better to POST, since we're not getting anything really, just showing quick example
$.get('save-attr.php?attr=xy_coord&value=300,550');
PHP:
// this will be the save-attr.php file
session_start();
$_SESSION[$_GET['attr']] = $_GET['value'];
// now any other script can get this value like so:
$coordinates = $_SESSION['xy_coord'];
// where $coordinates would now equal "300,550"
Simple continue this pattern for whatever you need access to in PHP

Double click an element using Selenium Webdriver - Facebook PHP library

I need to double click an dom element using Selenium Webdriver - Facebook PHP library.
There's no direct way to perform a double click on the element, but there's a way over WebDriverMouse this is how far I've got.
$myElement = $myWebDriver->findElement(WebDriverBy::id('myElement'));
$myWebDriver->getMouse()->doubleClick($myElement->getLocation());
Unfortunately this isn't working since ->getLocation returns an instance of WebDriverPoint but the method ->doubleClick() needs an instance of WebDriverCoordinates.
Is there an easier way to perform the double click or is there a way do create a WebDriverCoordinates instance out of a WebDriverPoint object?
Thank you very much for you help.
Sorry, was to fast with the question. Just figured it out:
$myElement = $myWebDriver->findElement(WebDriverBy::id('myElement'));
$myWebDriver->getMouse()->doubleClick($myElement->getCoordinates());
Here is an alternative using the action builder.
$myElement = $myWebDriver->findElement(WebDriverBy::id('myElement'));
$driver->actions()->doubleClick()->perform();
Also, $driver->actions() allows action chain / composite actions.
Drag and Drop example:
$driver->actions()->mouseDown($source)
->mouseMove($target)
->mouseUp($target);
->perform();
But actually, you can do drag and drop by just one method.
$driver->actions()->dragAndDrop($source, $target)->perform();

Building html structure in php or javascript?

I've been doing a lot of ajax calls and using the returned data to build html with javascript. However, I've noticed some people are returning the constructed html in the ajax calls since they're doing it all in php.
What is the preferred method? I have a bunch of stuff already using javascript, so I guess I would prefer not changing everything to use just php. But, I'm assuming php would be more "secure."?
The following is what I've been doing:
$main_frag = $("<div class='order-container'/>");
$contact_frag = $("<div class='group'><div class='line-data'>Name: "+data.name+"</div><div class='line-data'>Email: "+data.email+"</div><div class='line-data'>Phone: "+data.phone+"</div></div>");
$address_frag = $("<div class='group'><div class='line-data'>Address 1: "+data.address_one+"</div><div class='line-data'>Address 2: "+address2+"</div><div class='line-data'>City: "+data.city+"</div><div class='line-data'>Province: "+data.province+"</div><div class='line-data'>Postal Code: "+data.postal+"</div></div>");
etc..
I just want to hear the opinions of the community.
Look at some Javascript template solutions, such as Underscore.js (http://underscorejs.org/). Which is just an example, there's many. This should give you more separation and flexibility than just JQuery.
Also for more complex Javascript logic, you should consider to start using some Javascript MVC framework, such as Backbone.js (http://backbonejs.org/). Again there's many.
For browser / server communication, you can use JSON.
I don't think that retrieving them in parts or as a whole structure will have difference. both of them can be changed either via MITB ( Man in The Browser ) or even simple using developr tools that let you modify JS and HTML in the Browser..
IMO mustache is a good choice: http://coenraets.org/blog/2011/12/tutorial-html-templates-with-mustache-js/
with mustache you can use templates within your javascript to generate the markup

What's the correct way to call MooTools JS code from within Joomla?

I wrote some MooTools code that reads from YouTube's API in JSON and I want to execute it from within a custom component.
I've been reading about the js.php file, but I'm unclear on the best approach. I was just going to output js in my component directly, and then i realized that the MooTools library isn't being loaded unless a component specifically requests it.
Furthermore, part of my code was to dynamically load a remote JS Library, and then to remove it from the DOM when I needed. Can all this be done within Joomla's Framework?
Can someone help?
So it appears, there is a command in the framework that instantiates mootools, and several other commands for loading scripts into the DOM:
JHTML::_('behavior.mootools');
$doc = JFactory::getDocument()
$doc->addScript($scriptURL);
or a shortcut(from API docs):
JHTML::script(string $filename, [boolean $path = 'media/system/js/'], [ $mootools = true])
The thing is Joomla1.5 uses an older version of MooTools (1.1), and the next version that's going to be released is 2.0, so it's pretty far behind.
There are some interesting built-in features with the JHTML class, but I'm opting to use JQuery for most everything at this point - as updating MooTools will actually break many features in Joomla, and jQuery is much more lightweight.

Scraping Library for PHP - phpQuery?

I'm looking for a PHP library that allows me to scrap webpages and takes care about all the cookies and prefilling the forms with the default values, that's what annoys me the most.
I'm tired of having to match every single input element with xpath and I would love if something better existed. I've come across phpQuery but the manual isn't much clear and I can't find out how to make POST requests.
Can someone help me? Thanks.
#Jonathan Fingland:
In the example provided by the manual for browserGet() we have:
require_once('phpQuery/phpQuery.php');
phpQuery::browserGet('http://google.com/', 'success1');
function success1($browser)
{
$browser->WebBrowser('success2')
->find('input[name=q]')->val('search phrase')
->parents('form')
->submit();
}
function success2($browser)
{
echo $browser;
}
I suppose all the other fields are scrapped and send back in the GET request, I want to do the same with the phpQuery::browserPost() method but I don't know how to do it. The form I'm trying to scrape has a input token and I would love if phpQuery could be smart enough to scrape the token and just let me change the other fields (in this case username and password), submiting via POST everything.
PS: Rest assured, this is not going to be used for spamming.
See http://code.google.com/p/phpquery/wiki/Ajax and in particular:
phpQuery::post($url, $data, $callback, $type)
and
# data Object, String which defines the data parameter as being either an Object or a String. POST requests should be possible using query string format, e.g.:
$data = "username=Jon&password=123456";
$url = "http://www.mysite.com/login.php";
phpQuery::post($url, $data, $callback, $type)
as phpQuery is a jQuery port the method signature is the same (the docs link directly to the jquery site -- http://docs.jquery.com/Ajax/jQuery.post)
Edit
Two things:
There is also a phpQuery::browserPost function which might meet your needs better.
However, also note that the success2 callback is only called on the submit() or click() methods so you can fill in all of the form fields prior to that.
e.g.
require_once('phpQuery/phpQuery.php');
phpQuery::browserGet('http://www.mysite.com/login.php', 'success1');
function success1($browser) {
$handle = $browser
->WebBrowser('success2');
$handle
->find('input[name=username]')
->val('Jon');
$handle
->find('input[name=password]')
->val('123456');
->parents('form')
->submit();
}
function success2($browser) {
print $browser;
}
(Note that this has not been tested, but should work)
I've used SimpleTest's ScriptableBrowser for such stuff in the past. It's part of the SimpleTest testing framework, but you can use it stand-alone.
I would use a dedicated library for parsing HTML files and a dedicated library for processing HTTP requests. Using the same library for both seems like a bad idea, IMO.
For processing HTTP requests, check out eg. Httpful, Unirest, Requests or Guzzle. Guzzle is especially popular these days, but in the end, whichever library works best for you is still a matter of personal taste.
For parsing HTML files I would recommend a library that I wrote myself : DOM-Query. It allows you to (1) load an HTML file and then (2) select or change parts of your HTML pretty much the same way you'd do it if you'd be using jQuery in a frontend app.

Categories