lalao
lalao

Reputation: 11

CSS and XPath selectors in CasperJS

this function works very well, (this gives all <div class = "menuFamille" ..> for each <div class = "menuRayonContent avecLiens" ..> )

function getnb1() {
  var num1 = document.querySelectorAll(".menuRayonContent.avecLiens .menuFamille");// I get all divs menuFamille each div with class as "menuRayonContent avecLiens"
  return Array.prototype.map.call(num1, function (e) {
     try {
         return (/url\?q=(.*)&sa=U/).exec(e.getAttribute("href"))[1]
     } catch (err) {
         return e.getAttribute("href");
     }
  });
}

But there div whose class is simply "menuRayonContent" so the result gives 0 and I don't know how to find all divs with class as with or without "avecLiens"

and I will proceed as it

function getnb2() {
  var num1 = document.querySelectorAll (".menuRayonContent .menuFamille"); // I get all //divs menuFamille each div with class as "menuRayonContent"
  return Array.prototype.map.call(num1, function (e) {
      try {
         return (/url\?q=(.*)&sa=U/).exec(e.getAttribute("href"))[1]
      } catch (err) {
         return e.getAttribute("href");
      }
  });
}

This account all <div class = "menuFamille" ..> in the page.

and as the page is like this

<div class = "menuRayonContent avecLiens" style = "display: block;">
<div class = "menuFamille" idCat = "1024" typecat = "2">
<div class = "menuFamille" idCat = "1025" typecat = "2">
<div class = "menuFamille" idCat = "1026" typecat = "2">
<div class = "menuFamille" idCat = "290" typecat = "2">
<div class = "menuFamille" idCat = "2595" typecat = "2">
  ..........
  ...........
<div class = "menuRayonContent " style = "display: none;">
<div class = "menuFamille" idCat = "4024" typecat = "2">
<div class = "menuFamille" idCat = "1325" typecat = "2">
<div class = "menuFamille" idCat = "1226" typecat = "2">
<div class = "menuFamille" idCat = "2590" typecat = "2">
<div class = "menuFamille" idCat = "1595" typecat = "2">
.............
.............
<div class = "menuRayonContent " style = "display: none;">
<div class = "menuFamille" idCat = "4024" typecat = "2">
<div class = "menuFamille" idCat = "1325" typecat = "2">
<div class = "menuFamille" idCat = "1226" typecat = "2">
<div class = "menuFamille" idCat = "2590" typecat = "2">
<div class = "menuFamille" idCat = "1595" typecat = "2">

...........
...........

Or like this

<div class = "menuRayonContent avecLiens" style = "display: none;">
<div class = "menuFamille" idCat = "1024" typecat = "2">
<div class = "menuFamille" idCat = "1025" typecat = "2">
<div class = "menuFamille" idCat = "1026" typecat = "2">
<div class = "menuFamille" idCat = "290" typecat = "2">
<div class = "menuFamille" idCat = "2595" typecat = "2">
..........
...........
<div class = "menuRayonContent " style = "display: block;">
<div class = "menuFamille" idCat = "4024" typecat = "2">
<div class = "menuFamille" idCat = "1325" typecat = "2">
<div class = "menuFamille" idCat = "1226" typecat = "2">
<div class = "menuFamille" idCat = "2590" typecat = "2">
<div class = "menuFamille" idCat = "1595" typecat = "2">
.............
.............
<div class = "menuRayonContent " style = "display: none;">
<div class = "menuFamille" idCat = "4024" typecat = "2">
<div class = "menuFamille" idCat = "1325" typecat = "2">
<div class = "menuFamille" idCat = "1226" typecat = "2">
<div class = "menuFamille" idCat = "2590" typecat = "2">
<div class = "menuFamille" idCat = "1595" typecat = "2">
...........
...........

I think of counting divs with class attributes = "menuRayonContent" or class = "menuRayonContent avecLiens" and style = "display: block;" but until now I can't, (I use casperjs)

this is my function:

function getnb() {
  var links = __utils__.getElementsByXPath(x('//div[contains(class, "menuRayonContent" && style = "display: block;")]'));
  return Array.prototype.map.call (links, function (e) {
     return e.getAttribute('href');
  });
}

Upvotes: 1

Views: 999

Answers (1)

Artjom B.
Artjom B.

Reputation: 61892

Now that all the typos are gone, to reiterate you want to select all .menuFamille elements under .menuRayonContent which are visible and you want them separate. This mean that you have to iterate over the container and then iterate over the children.

The clientutils module of CasperJS has an undocumented function {boolean} elementVisible({DOM element} elem). You can use this to iterate over all visible .menuRayonContent and then build a list with their children.

var container = document.querySelectorAll(".menuRayonContent");
container = Array.prototype.map.call(container, function (c) {
    var obj = {
        number: 0,
        children: null,
        visible: __utils__.elementVisible(c),
        className: c.getAttribute("class")
    };
    var children = c.querySelectorAll(".menuFamille");
    children = Array.prototype.map.call(children, function (child) {
        return child.getAttribute("idCat"); // or something else that you need
    });
    obj.number = children.length;
    obj.children = children;
    return obj;
});

For your example DOM this should yield:

container = [
    {
        number: 5,
        children: [
            "1024", "1025", "1026", "290", "2595"
        ],
        visible: true,
        className: "menuRayonContent avecLiens"
    },
    {
        number: 5,
        children: [
            "4024", "1325", "1226", "2590", "1595"
        ],
        visible: true,
        className: "menuRayonContent"
    }
];

You can of course remove filter out invisible .menuRayonContent elements using

var container = document.querySelectorAll(".menuRayonContent[style*='display'][style*='block']");

The [attr*='value'] matches all elements whose attr attribute contains value somewhere.

Upvotes: 1

Related Questions