Kawd
Kawd

Reputation: 4440

How do I check if a selector contains sub-selector X in SASS?

here's the function I'm trying to create :

@function contains-selector ($selector, $subselector) {
  @return str_index($selector,$subselector);
}

but I believe it will return true even for the '.weird-selecto' case that you see below, which is wrong.

example :

#some .long .weird-selector {
}

//should return true
contains-selector('#some .long .weird-selector', '.weird-selector') 

//should return false
contains-selector('#some .long .weird-selector', '.weird-selecto')

Upvotes: 0

Views: 319

Answers (1)

Daisi
Daisi

Reputation: 2418

You could use this approach although it looks a bit complicated

@function contains-selector ($selector, $subselector) {
  $start_index: str-index($selector, $subselector);
  $selector_found: null;
  @if ($start_index == null) {
    $selector_found: false;
  } @else {
    $end_index: $start_index + str-length($subselector) - 1;
    @while( ($end_index <= str-length($selector)) and (str-slice($selector, $end_index, $end_index) != ' ')) {
      $end_index: $end_index + 1;
    }
    $word: str-slice($selector, $start_index, $end_index - 1);
    $selector_found: if($word == $subselector, true, false);
  }
  @return $selector_found;
}

Using the function in the following situations

@debug contains-selector('#some .long .weird-selector', '#arbitrary-text'); //false
@debug contains-selector('#some .long .weird-selector', '.wei');            //false
@debug contains-selector('#some .long .weird-selector', '#some');           //true
@debug contains-selector('#some .long .weird-selector', '.weird-selector'); //true
@debug contains-selector('#some .long .weird-selector', '.weird-select');   //false

The way str-index works is that it gets the starting index of a substring found within a string or null if can't find a matching substring.

str_index('.weird-selector', '.where') returns null because the substring where can't be found in weird-selector while str_index('.weird-selector', '.weird-selec'); returns 1 because the substring .weird-selec can be found at the 1st position of the string .weird-selector

In the if condition of the method, if the subselector is not found in the selector, the str-index returns null and the method returns false
@debug contains-selector('#some .long .weird-selector', '#arbitrary-text'); //false

In the else block, we know that the subselector found in the selector is similar but not if they are the same.
Using str_index('#some .weird-selector .long', '.weird-selec'), we can see weird-selec is in the string but the actual word in the string is weird-selector. So the loop in the block is responsible for getting the end_index of the word in the string. Once the word has been found, it is compared to the subselector and the method returns true if they match or false otherwise.

Hope this helps :)

Upvotes: 1

Related Questions