I have to write by.cssContainingText() in chrome console .This is regarding protractor.
Inside the implement of by.cssContainingText(cssSelector, searchText), it does two steps:
run querySelectorAll(cssSelector) to get a element list
iterate the element list to find which one's text match the searchText
Following is implement code of cssContainingText(), you also can find it at github
functions.findByCssContainingText = function(cssSelector, searchText, using) {
using = using || document;
if (searchText.indexOf('__REGEXP__') === 0) {
var match = searchText.split('__REGEXP__')[1].match(/\/(.*)\/(.*)?/);
searchText = new RegExp(match[1], match[2] || '');
}
var elements = using.querySelectorAll(cssSelector);
var matches = [];
for (var i = 0; i < elements.length; ++i) {
var element = elements[i];
var elementText = element.textContent || element.innerText || '';
var elementMatches = searchText instanceof RegExp ?
searchText.test(elementText) :
elementText.indexOf(searchText) > -1;
if (elementMatches) {
matches.push(element);
}
}
return matches;
};
It's more complex to write equivalent in browser's console, but you can do as following:
Open stackoverflow site: https://stackoverflow.com/
execute following example code in browser console
expand the return result in console
mouse over on each item of return result in console, then you can notice the mouse will over on the corresponding element on page as following screenshot
Example code:
Array.from(document.querySelectorAll('li > a')).filter((it)=>{return (it.textContent || it.innerText || '').contains('Users')})
Screenshot of example:
This isn't a good way to approach it lets see the syntax
<ul>
<li class="pet">Dog</li>
<li class="pet">Cat</li>
</ul>
// Returns the li for the dog, but not cat.
var dog = element(by.cssContainingText('.pet', 'Dog'));
inside the bracket the first argument is the .classname and the second argument is the actual text .Better write it in script and check it .it'll work
Related
I'm trying to replicate what was done in this answer for java selenium in RSelenium: https://stackoverflow.com/a/27611777/7837376
I'd love to be able to do something like this:
#replicating simple RSelenium process getting all //a elements
library(RSelenium)
#start remDr etc. etc.
all_a <- remDr$findElements(using='xpath','//a')
selected_a <- all_a[[10]]
Ideally then I could generate the xpath of the selected_a element using the made up function below:
#desired function
getElementXPATH(selected_a)
I understand that quite a few different XPATH's could be specified for the same element, I'm just looking for a unique xpath identifier for the element, so any unique xpath to the element will suffice!
Thanks!
Personally, I am not a big fan absolute xpath. However, you can get the absolute xpath using javascript rather having the function in your language, which will ran faster and it's easy to port.
Here is the javascript.
// this function will return the absolute xpath of any given element
jsFunction = """window.getAbsoluteXpath =function(el){
// initialize the variables
aPath ="";
// iterate until the tag name is 'HTML'
while (el.tagName!='HTML'){
// get parent node
pEle=el.parentNode;
// check if there are more than 1 nodes with the same tagname under the parent
if(pEle.querySelectorAll(el.tagName).length>1){
//now findout the index of the current child
cIndex = 0;
pEle.querySelectorAll(el.tagName).forEach(function(cEle){
cIndex= cIndex+1;
// check if iterating ChildNode is equal to current ChildNode
if(cEle === el){
// set the aPath using index
aPath = el.tagName + "[" + cIndex + "]" + "/" +aPath;
}
})
}else{
// simply add the tagName when there is only one child with the tag name
aPath = el.tagName + "/" +aPath;
}
// set parent node as current element
el=el.parentNode;
}
// append HTML to the absolute xpath generated
return "//HTML/"+aPath.substring(0,aPath.length-1);
};"""
Now you can call this method in your javascript and pass element that you are interested in getting the absolute xpath.
Let's try to get the absolute xpath of in stackoverflow.
Note: Did not tested the below code logic due to lack of environment on my machine.
# run the javascript in browser so that you can call the function anytime in your script
remDr %>% executeScript(jsFunction, args = list())
# get stackoverflow `Achievements` link element
webElem <- remDr %>% findElement("css", "a.-link.js-achievements-button")
# # get the absolute xpath of Stackoverflow `Achievements`
remDr %>% executeScript("return getAbsoluteXpath(arguments[0])", args = list(webElem))
Screenshot: Ran the javascript in chrome browser console for evidence
Please try the below logic
function absolutePath(element) {
if (element.tagName.toLowerCase() == 'html')
return '/html[1]';
if (element === document.body)
return '/html[1]/body[1]';
var ix = 0;
var siblings = element.parentNode.childNodes;
for (var i = 0; i < siblings.length; i++) {
var sibling = siblings[i];
if (sibling === element)
return absolutePath(element.parentNode) + '/' + element.tagName.toLowerCase() + '[' + (ix + 1) + ']';
if (sibling.nodeType === 1 && sibling.tagName.toLowerCase() === element.tagName.toLowerCase())
ix++;
}}
I did try the solution provided by supputuri, but it doesnt work on all cases.
Example: Try the function provided by #suppututri on https://www.amazon.in/ , and try to find the absolute xpath for
var element=document.querySelector('#nav-xshop > a:nth-child(2)');
getAbsoluteXpath(element);
The incorrect xpath shown in the console would be: "//HTML/BODY/DIV[1]/HEADER/DIV[1]/DIV[68]/DIV[9]/DIV[1]/DIV/A[1]"
How can I extract information from a web page into an Excel sheet?
The website is https://www.proudlysa.co.za/members.php and I would like to extract all the companies listed there and all their respective information.
The process you're referring to is called web scraping, and there are several VBA tutorials out there for you to try.
Alternatively, you can always try
(source: netdna-ssl.com)
I tried creating something to grab for all pages. But ran of time and had bugs. This should help you a little. You will have to do this on all 112 pages.
Using chrome go to the page
type javascript: in the url then paste the code below. it should extra what you need. then you will have to just copy and paste it in to excel.
var list = $(document).find(".pricing-list");
var csv ="";
for (i = 0; list.length > i;i++) {
var dataTags = list[i].getElementsByTagName('li');
var dataArr = [];
for (j = 0; dataTags.length > j;j++) {
dataArr.push(dataTags[j].innerText.trim());
}
csv += dataArr.join(', ') + "<br>";
}
you will get something like this
EDITTED
use this instead will automatically download each page as csv then you can just combine them after somehow.
Make sure to type javascript: in url before pasting and pressing enter
Also works with chrome, not sure about other browsers. i dont use them much
var list = $(document).find(".pricing-list");
var csv ="data:text/csv;charset=utf-8,";
for (i = 0; list.length > i;i++) {
var dataTags = list[i].getElementsByTagName('li');
var dataArr = [];
for (j = 0; dataTags.length > j;j++) {
dataArr.push(dataTags[j].innerText.trim());
}
csv += dataArr.join(', ') + "\n";
}
var a = document.createElement("a");
a.href = ""+ encodeURI(csv);
a.download = "data.csv";
a.click();
This question already has answers here:
How to identify unused CSS definitions from multiple CSS files in a project
(3 answers)
Closed 9 years ago.
I was thinking of writing a script which would tell me:
How often each CSS class defined in my .css file is used in my code
Redundant CSS classes - classes never used
CSS classes hat are referenced that don't exist.
But I just want to make sure something like this doesn't exist already? Does it?
Thanks
Just for fun, I wrote one.
try it
First we need to find our style sheet. In an actual script, this would be written better, but this works on jsFiddle.
var styles = document.head.getElementsByTagName('style');
var css = styles[styles.length - 1].innerHTML;
Then remove comments, and the bodies of each selector (i.e. the stuff between the brackets). This is done because there could be a .com in a background-image property, or any number of other problems. We assume there isn't a } in a literal string, so that would cause problems.
var clean = css.replace(/\/\*.*?\*\//g, '').replace(/\{[^}]*\}/g, ',');
We can find classes with regular expressions, and then count how many of them occur.
var re_class = /\.(\w+)/g;
var cssClasses = {}, match, c;
while (match = re_class.exec(clean)) {
c = match[1];
cssClasses[c] = cssClasses[c] + 1 || 1;
}
I used jsprint for displaying our findings. This shows how many times each class is mentioned in our CSS.
jsprint("css classes used", cssClasses);
Thanks to Google and this answer we can find all elements in the body, and loop through them. By default, we assume no classes were used in our HTML, and all classes used were defined.
var elements = document.body.getElementsByTagName("*");
var neverUsed = Object.keys(cssClasses);
var neverDefined = [];
var htmlClasses = {};
We get each elements class, and split it on the spaces.
for (var i=0; i<elements.length; i++) {
var e = elements[i];
var classes = (e.className || "").split(" ");
This is a three dimensional loop, but it works nicely.
for (var j=0; j<classes.length; j++) {
for (var k=0; k<neverUsed.length; k++) {
We thought classes[j] was never used, but we found a use of it. Remove it from the array.
if (neverUsed[k] === classes[j]) {
neverUsed.splice(k, 1);
}
}
It looks like we found a class that doesn't appear in our CSS. We just need to make sure it's not an empty string, and then push it onto our array.
if (classes[j].length && cssClasses[classes[j]] == null) {
neverDefined.push(classes[j]);
}
Also count the number of times each class is used in HTML.
if (classes[j].length) {
htmlClasses[classes[j]] = htmlClasses[classes[j]] + 1 || 1;
}
}
}
Then display our results.
jsprint("html class usage", htmlClasses);
jsprint("never used in HTML", neverUsed);
jsprint("never defined in CSS", neverDefined);
I would like a way to obtain an HTML element or CSS selector (or a reference to the droppable object itself) for the date on which an external draggable element was dropped. I tried using the following within the drop() callback to get the node for the date box using the coordinates of the drop event:
var pageX = jsEvent.originalEvent.pageX;
var pageY = jsEvent.originalEvent.pageY;
var domElem = document.elementFromPoint(pageX, pageY);
var node = Y.one(domElem).ancestor('#calendar > .fc-content table.fc-border-separate tr > td', true);
(I'm using the YUI 3 Y.one() and ancestor() methods above to get the node I want, but other methods could be used.)
The above does correctly locate the node of the date box as long as the drop does NOT land on top of an event cell rendered on that date. If the drop does happen to land on an event cell, however, domElem ends up being the event cell, which is an absolutely positioned element outside of the calendar, and the ancestor() methodology above does not work.
I have also tried getting a reference to the droppable obj by way of the draggable element revert property:
revert: function(droppableObj) {
if(droppableObj === false) {
alert('No droppableObj');
return true;
}
else {
alert(Y.dump({droppableObj: droppableObj}));
return false;
}
},
Unfortunately, the above does not work. Even though the external element does drop correctly, the revert function does not recognize the calendar as droppable. (For details, see my earlier stackoverflow post at: Fullcalendar: draggable object rejects fullcalendar as droppable even though fullcalendar accepts drop )
The only alternative I can think of is to use the date object in the drop() callback, and with that find the correct fc-dayXX element, but that seems pretty cumbersome. I have searched on this already, but not found anything so far. If anyone has a suggestion, please let me know.
Here is what I came up with for the fullcalendar drop callback:
function getSelectorForDroppedOnDate(date, allDay, jsEvent, ui) {
if (! date) return;
var displayedDate = $('#calendar').fullCalendar('getDate');
var displayedMonth = displayedDate.getMonth(); // 0 - 11
var displayedYear = displayedDate.getFullYear();
var droppedOnYear = date.getFullYear();
var droppedOnMonth = date.getMonth(); // 0 - 11
var droppedOnDate = date.getDate(); // 1 - 31
var droppedOnDayOfWeek = date.getDay(); // 0 - 6 no matter what week of the month
// Get values related to the last day of the month before the month the event was dropped on
// so that the grid location of the drop can be determined
var lastDayOfMonthBeforeDroppedOnMonth = new Date(droppedOnYear, droppedOnMonth, 0); // This is actually correct
var dateOfLastDayOfMonthBeforeDroppedOnMonth = lastDayOfMonthBeforeDroppedOnMonth.getDate(); // 1 - 31
var dayOfWeekOfLastDayOfMonthBeforeDroppedOnMonth = lastDayOfMonthBeforeDroppedOnMonth.getDay(); // 0 - 6
var i;
var gridLocationOfDrop; // 0 - 41 to cover 42 days of six weeks always shown
if (droppedOnMonth === displayedMonth) { // dropped on month is same as currently displayed month
i = 0;
// adjust droppedOnDayOfWeek by 1 to account for 0-based index
while ((droppedOnDayOfWeek + 1) + i*7 < droppedOnDate) {
i++;
}
gridLocationOfDrop = droppedOnDayOfWeek + i*7;
}
else {
// if dropped on date is in month previous to currently displayed month (need to compare years since inequality will reverse at year boundary)
if ((droppedOnMonth < displayedMonth && droppedOnYear === displayedYear) || (droppedOnMonth > displayedMonth && droppedOnYear < displayedYear)) {
gridLocationOfDrop = droppedOnDayOfWeek;
}
// else if dropped on date is in month after currently displayed month (need to compare years since inequality will reverse at year boundary)
else if ((droppedOnMonth > displayedMonth && droppedOnYear === displayedYear) || (droppedOnMonth < displayedMonth && droppedOnYear > displayedYear)) {
i = 0;
// adjust dayOfWeekOfLastDayOfMonthBeforeDroppedOnMonth by 1 to account for 0-based index
while ((dayOfWeekOfLastDayOfMonthBeforeDroppedOnMonth + 1) + i*7 < dateOfLastDayOfMonthBeforeDroppedOnMonth) {
i++;
}
gridLocationOfDrop = (dayOfWeekOfLastDayOfMonthBeforeDroppedOnMonth + i*7 + droppedOnDate);
}
}
selector = '#calendar > .fc-content table tr > td.fc-day' + gridLocationOfDrop;
return selector;
}
Works for me!
I have a set of components that are added to my Flex 4 stage dynamically.
Problem 1:
How do I address these objects when adding them to print.I cant generate objects on the fly and append them because then the print manager does not wait for the dynamic data to populate.
I currently use the following code to address items dynamically which fails:
public function PrintDashPreview():void{
var ItemsDrawn:int = 0;
var printJob:FlexPrintJob = new FlexPrintJob();
if(printJob.start()){
for each (var item:Object in GetDashBoardPreviewItems.lastResult.DashboardItem)
{
ItemsDrawn ++
this.addElement(dashPreview["flexShape" + TheID]);
printJob.addObject(dashPreview["flexShape" + TheID]);
this.removeElement(dashPreview["flexShape" + TheID]);
}
printJob.send()
Alert.show('Sent: ' + ItemsDrawn + ' items to page for printing.','Print Progress Debug');
}
}
How can I tell flex to grab these specific items and add them to the print job.
Problem 2:
How do I tell flex to lay each item out one below the other 2 per page.
Please and thank you for any help you can provide.
Regards
Craig Mc
The recipe for printing dynamic content usually goes like this:
(1) Start the printJob:
printJob = new FlexPrintJob();
printJob.printAsBitmap = false;
printJob.start();
(2) Obtain the print page dimensions. Use it if you have overflowing content:
printerPageHeight = printJob.pageHeight;
printerPageWidth = printJob.pageWidth;
(3) Create all of the dynamic objects and wait for the corresponding CREATION_COMPLETE events:
var componentsToBeInitialized:Number = 0;
var pages:Array = [];
for each (var itemData:Object in dataProvider) {
var component:UIComponent = new PageComponent();
someContainerOnTheDisplayList.addChild(component);
component.data = itemData;
componentsToBeInitialized ++;
pages.push(component);
component.addEventListener(FlexEvent.CREATION_COMPLETE, handlePageCompletion);
}
(4) Waiting for all CREATION_COMPLETE events:
function handlePageCompletion(e:Event):void {
componentsToBeInitialized --;
if (componentsToBeInitialized == 0)
printAllPages();
}
(5) Print the pages:
function printAllPages():void {
for each (var printPage:UIComponent in pages) {
printJob.addObject(printPage);
}
printJob.send();
}