Add support for [attr|="value"] selector (prefix selector)
Jakub Narebski [Sun, 9 Jan 2011 13:27:44 +0000 (14:27 +0100)]
http://www.w3.org/TR/css3-selectors/#attribute-selectors
http://www.w3.org/TR/CSS2/selector.html#attribute-selectors
http://api.jquery.com/attribute-contains-prefix-selector/

  Description: Selects elements that have the specified attribute with
  a value either equal to a given string or starting with that string
  followed by a hyphen (-).

  This selector was introduced into the CSS specification to handle
  language attributes.

Note that this selector is primarily intended to allow language
subcode matches (e.g., the `hreflang` attribute on the <a> element in
HTML; for `lang` or `xml:lang` attribute there is `:lang`
pseudo-class selector).

lib/HTML/Zoom/SelectorParser.pm
t/selectors.t

index ef61d93..929e9a7 100644 (file)
@@ -92,6 +92,17 @@ sub _raw_parse_simple_selector {
         }
       };
 
+    # '[attr!=bar]' - match attribute contains prefix (for language matches)
+    /\G\[$sel_re\|=$match_value_re\]/gc and
+      return do {
+        my $attribute = $1;
+        my $value = $2;
+        sub {
+          $_[0]->{attrs}{$attribute}
+          && $_[0]->{attrs}{$attribute} =~ qr/^\Q$value\E(?:-|$)/;
+        }
+      };
+
     # '[attr=bar]' - match attributes
     /\G\[$sel_re=$match_value_re\]/gc and
       return do {
index e6be2c2..41699bf 100644 (file)
@@ -104,6 +104,16 @@ is( HTML::Zoom->from_html('<div frew="foo bar baz"></div>'.$stub)
    '<div frew="foo bar baz">grg</div>'.$stub,
    'E[attr~="val"] works' );
 
+# el[attr|="foo"]
+is( HTML::Zoom->from_html('<div lang="pl"></div><div lang="english"></div>'.
+                          '<div lang="en"></div><div lang="en-US"></div>'.$stub)
+   ->select('div[lang|="en"]')
+      ->replace_content('grg')
+   ->to_html,
+   '<div lang="pl"></div><div lang="english"></div>'.
+   '<div lang="en">grg</div><div lang="en-US">grg</div>'.$stub,
+   'E[attr|="val"] works' );
+
 # [attr=bar]
 ok( check_select( '[prop=moo]'), '[attr=bar]' );