Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Match jQuery element tree traversing interface #18

Open
4 tasks
iobaixas opened this issue Sep 13, 2015 · 4 comments
Open
4 tasks

Match jQuery element tree traversing interface #18

iobaixas opened this issue Sep 13, 2015 · 4 comments

Comments

@iobaixas
Copy link
Member

iobaixas commented Sep 13, 2015

The idea is to match JQuery's interface as closely as possible.
JQuery provides some tree traversal utilities:
https://api.jquery.com/category/traversing/tree-traversal/

These are particularly interesting:

  • children()
  • closest()
  • parent()
  • siblings()
@Ssruno
Copy link

Ssruno commented Jan 22, 2018

Hello team!

For the children() utility I have a proposal here (with a minor fix for rspec here). The proposal tries to re-utilize the existing functions in order to avoid big changes.

For the children() utility I have a proposal here.

According to the jQuery API: https://api.jquery.com/children/

For the given HTML of example:

<ul class="level-1">
  <li class="item-i">I</li>
  <li class="item-ii">II
    <ul class="level-2">
      <li class="item-a">A</li>
      <li class="item-b">B
        <ul class="level-3">
          <li class="item-1">1 Orange</li>
          <li class="item-2">2 Watermelon</li>
          <li class="item-3">3 Apple</li>
        </ul>
      </li>
      <li class="item-c">C</li>
    </ul>
  </li>
  <li class="item-iii">III</li>
</ul>

And this code:

Pincers.for_webdriver :chrome do |pincers|
  Pincers.goto "URL"
  # Direct call without a selector and in conjunction with search()
  test1  = pincers.search(".level-2").children()
  # Call with a selector
  test2  = pincers.children(".level-2")
end

We can have the expected behavior for test1 and test2:

<li class="item-a">A</li>
<li class="item-b">B
   <ul class="level-3">
      <li class="item-1">1 Orange</li>
      <li class="item-2">2 Watermelon</li>
      <li class="item-3">3 Apple</li>
   </ul>
</li>
<li class="item-c">C</li>

@Ssruno
Copy link

Ssruno commented Jan 22, 2018

For the parent() utility there is a little issue; the attr_reader :parent present in the search_context.rb file defines a parent() method in the SearchContext class. Therefore, for the sake of functionality I implemented the parent() method with a different name: parent_jq(). The implementation is here.

If it's strictly desirable to use the parent() name for the utility, the way around would be to change the attr_reader name of :parent

According to the jQuery API: https://api.jquery.com/parent/

For the given HTML of example:

<ul class="level-1">
  <li class="item-i">I</li>
  <li class="item-ii">II
    <ul class="level-2">
      <li class="item-a">A</li>
      <li class="item-b">B
        <ul class="level-3">
          <li class="item-1">1 Orange</li>
          <li class="item-2">2 Watermelon</li>
          <li class="item-3">3 Apple</li>
        </ul>
      </li>
      <li class="item-c">C</li>
    </ul>
  </li>
  <li class="item-iii">III</li>
</ul>

And this code:

Pincers.for_webdriver :chrome do |pincers|
  Pincers.goto "URL"
  # Direct call without a selector and in conjunction with search()
  test1  = pincers.search(".level-3").parent_jq()
  # Call with a selector
  test2  = pincers.search(".level-3").parent_jq(".item-b")
end

We can have the expected behavior for test1 and test2:

<li class="item-b">B
   <ul class="level-3">
      <li class="item-1">1 Orange</li>
      <li class="item-2">2 Watermelon</li>
      <li class="item-3">3 Apple</li>
   </ul>
</li>

@Ssruno
Copy link

Ssruno commented Jan 22, 2018

For the siblings() utility I have a proposal here. The strategy was to use the Pincers::CSS::Parser class to translate the given selector and form a valid XPath, to finally be called through the existing search() function.

According to the jQuery API: https://api.jquery.com/siblings/

For the given HTML of example:

<ul class="level-1">
  <li class="item-i">I</li>
  <li class="item-ii">II
    <ul class="level-2">
      <li class="item-a">A</li>
      <li class="item-b">B
        <ul class="level-3">
          <li class="item-1">1 Orange</li>
          <li class="item-2">2 Watermelon</li>
          <li class="item-3">3 Apple</li>
        </ul>
      </li>
      <li class="item-c">C</li>
    </ul>
  </li>
  <li class="item-iii">III</li>
</ul>

And this code:

Pincers.for_webdriver :chrome do |pincers|
  Pincers.goto "URL"
  # Direct call without a selector and in conjunction with search()
  test1  = pincers.search(".item-2").siblings()
  # Call with a selector
  test2  = pincers.search(".item-2").siblings(".item-1")
end

We can have the expected behavior for test1:

      <li class="item-1">1 Orange</li>
      <li class="item-3">3 Apple</li>

We can have the expected behavior for test2:

      <li class="item-1">1 Orange</li>

@Ssruno
Copy link

Ssruno commented Jan 22, 2018

For the closest() utility I have a proposal here. The strategy was similar as before, nonetheless according to the jQuery API it should receive other type of parameters as i.e. context and element. I'll look for further instructions if this parameters are desirable, in the meanwhile I limited the implementation to the presence of a given selector.

For the given HTML of example:

<ul class="level-1">
  <li class="item-i">I</li>
  <li class="item-ii">II
    <ul class="level-2">
      <li class="item-a">A</li>
      <li class="item-b">B
        <ul class="level-3">
          <li class="item-1">1 Orange</li>
          <li class="item-2">2 Watermelon</li>
          <li class="item-3">3 Apple</li>
        </ul>
      </li>
      <li class="item-c">C</li>
    </ul>
  </li>
  <li class="item-iii">III</li>
</ul>

And this code:

Pincers.for_webdriver :chrome do |pincers|
  Pincers.goto "URL"
  # In conjunction with search(), selector is mandatory
  test1  = pincers.search("li.item-2").closest("ul")
  # Begins its search with the element itself before progressing up the DOM tree
  test2  = pincers.search("li.item-a").closest("li")
  # Raise an error for missing selector
  test3 = pincers.search("li.item-a").closest()
end

We can have the expected behavior for test1:

   <ul class="level-3">
      <li class="item-1">1 Orange</li>
      <li class="item-2">2 Watermelon</li>
      <li class="item-3">3 Apple</li>
   </ul>

We can have the expected behavior for test2:

      <li class="item-a">A</li>

Ssruno added a commit to Ssruno/pincers that referenced this issue Feb 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants