E[attr] and E[attr^="foo"]
[catagits/HTML-Zoom.git] / lib / HTML / Zoom / SelectorParser.pm
index 7d3c6a5..3395940 100644 (file)
@@ -2,6 +2,7 @@ package HTML::Zoom::SelectorParser;
 
 use strict;
 use warnings FATAL => 'all';
+use base qw(HTML::Zoom::SubObject);
 use Carp qw(confess);
 
 my $sel_char = '-\w_';
@@ -17,6 +18,62 @@ sub _raw_parse_simple_selector {
     /\G\*/gc and
       return sub { 1 };
 
+     # 'el[attr~="foo"]
+
+    /\G$sel_re\[$sel_re~="$sel_re"\]/gc and
+      return do {
+        my $name = $1;
+        my $attr = $2;
+        my $val = $3;
+        sub {
+          if (
+            $_[0]->{name} && $_[0]->{name} eq $name and
+            $_[0]->{attrs}{$attr}
+          ) {
+            my %vals = map { $_ => 1 } split /\s+/, $_[0]->{attrs}{$attr};
+            return $vals{$val}
+          }
+          return undef
+        }
+      };
+
+     # 'el[attr^="foo"]
+
+    /\G$sel_re\[$sel_re\^="$sel_re"\]/gc and
+      return do {
+        my $name = $1;
+        my $attr = $2;
+        my $val = $3;
+        sub {
+           $_[0]->{name} && $_[0]->{name} eq $name and
+           $_[0]->{attrs}{$attr} && $_[0]->{attrs}{$attr} =~ /^\Q$val\E/
+        }
+      };
+
+     # 'el[attr="foo"]
+
+    /\G$sel_re\[$sel_re="$sel_re"\]/gc and
+      return do {
+        my $name = $1;
+        my $attr = $2;
+        my $val = $3;
+        sub {
+           $_[0]->{name} && $_[0]->{name} eq $name and
+           $_[0]->{attrs}{$attr} && $_[0]->{attrs}{$attr} eq $val
+        }
+      };
+
+     # 'el[attr]
+
+    /\G$sel_re\[$sel_re\]/gc and
+      return do {
+        my $name = $1;
+        my $attr = $2;
+        sub {
+           $_[0]->{name} && $_[0]->{name} eq $name && $_[0]->{attrs}{$attr}
+        }
+      };
+
     # 'element' - match on tag name
 
     /\G$sel_re/gc and
@@ -41,7 +98,31 @@ sub _raw_parse_simple_selector {
         my @cl = split(/\./, $cls);
         sub {
           $_[0]->{attrs}{class}
-          && !grep $_[0]->{attrs}{class} !~ /\b$_\b/, @cl
+          && !grep $_[0]->{attrs}{class} !~ /(^|\s+)$_($|\s+)/, @cl
+        }
+      };
+
+    # 'el.class1' - element + class
+
+    /\G$sel_re\.$sel_re/gc and
+      return do {
+        my $cls = $1;
+        my $name = $2;
+        sub {
+           $_[0]->{name} && $_[0]->{name} eq $name and
+           $_[0]->{attrs}{class} && $_[0]->{attrs}{class} eq $cls
+        }
+      };
+
+    # 'el#id' - element + id
+
+    /\G$sel_re#$sel_re/gc and
+      return do {
+        my $id = $1;
+        my $name = $2;
+        sub {
+           $_[0]->{name} && $_[0]->{name} eq $name and
+           $_[0]->{attrs}{id} && $_[0]->{attrs}{id} eq $id
         }
       };
 
@@ -68,7 +149,7 @@ sub parse_selector {
       }
     };
   }
-} 
-  
+}
+
 
 1;