technosophos / querypath

QueryPath is a PHP library for manipulating XML and HTML. It is designed to work not only with local files, but also with web services and database resources.
http://querypath.org
Other
823 stars 115 forks source link

removeClass not removing multiple classes at once #77

Open GDmac opened 12 years ago

GDmac commented 12 years ago

When specifying multiple classes to remove, nothing happens. Or maybe i just don't get it

// doesn't work
$page->find('td')->removeClass('list odd even');

// nor
$page->find('td')->removeClass();

// awkward
$elems =  $page->find('td');
foreach ($elems as $item)
{
    $item->removeClass('list');
    $item->removeClass('odd');
    $item->removeClass('even');
}

_.removeClass( [className] )_ _className_ One or more space-separated classes to be removed from the class attribute of each matched element. http://api.jquery.com/removeClass/

technosophos commented 12 years ago

Yeah, the current implementation of removeClass() only removes a single class.

I think adding functionality for removeClass(array('a', 'b', 'c')) might not be a bad idea.

For now, though, the only other immediate option would be for you to parse the 'class' attribute value and manage that directly, and that's not really any more elegant.

I'd like your input on turning this into a feature request. I'm very actively working on the 3.x release right now, so it's a good time to ask for something. ;-)

GDmac commented 12 years ago

how about a little recursion in the removeClass method,

$classes_to_remove = array_filter(explode(' ',$class));
if(empty($classes_to_remove))
{
    removeAttr('class');
}
else
{
    foreach ($classes_to_remove as $className)
    {
        removeClass($Classname);
    }
}

/rant: QueryPath is amazing, but finding stuff in the documentation is a bit awkward It really needs a good centralized (consolidated) user_guide

Today, was generating a mRSS feed from the $rss_item_stub, but with an extra <media:content> ...

Normally i would just resort to echo items in a loop, but the benefit of using Querypath is generating valid XML. Nowhere couId i find a simple explanation, (google-google) i tried various things and finally when almost giving up, added a xmlns <item xmlns:media="http://search.yahoo.com/mrss/">

GDmac commented 12 years ago

Pull Request on 3.x branch https://github.com/technosophos/querypath/pull/78

technosophos commented 12 years ago
  1. I will take a look at the pull request later today (I hope) or tomorrow.
  2. I agree about a user's guide. With Doxygen adding (I hope) Markdown support, it might become possible in the near future to write a nice Markdown-formatted guide and have it fully integrate into the API docs.
  3. It sounds like you solved the namespace issue, right? Namespacing has been the single hardest egg to crack due the stringent requirements of XML and the rather vague handling in CSS 3.
GDmac commented 12 years ago

yes, adding a xmlns to item seems to work Don't ask me why or how, it works :-)

    $rss_item_stub = '<?xml version="1.0" encoding="utf-8"?>
    <item xmlns:media="http://search.yahoo.com/mrss/">
      <title></title>
      <link></link>
      <description></description>
      <category>image</category>
      <guid isPermaLink="false"></guid>
      <media:content medium="image"></media:content>
    </item>
GDmac commented 12 years ago

oh,by the way, qp( $rss_item_stub, 'title')->next('description')->text('blah')->next('link')->text('')... gives an exception on some servers, if the items aren't in the order in the stub as they are called. Also i have seen errors after qp->find(x)-doStuff(); followed by a qp->find('y')->otherStuff(); Somehow matched items in the first call might not be cleared when starting anew, with a new chain. Maybe this could be fixed.

I mean, its problematic if i issue qp->top()->find('div')->... instead of qp->find('div')->... just to be sure...

technosophos commented 12 years ago

Instead of using next() you should use siblings(). The next() method follows jQuery's behavior, requiring that the element be immediately adjacent. siblings() selects any element with the same parent.

I'm not positive that I understand the find() problem (an example might help), but I think that what you might want is to use branch() instead of find(). If you've got a bug, though, definitely file it as a separate issue and I'll take a look.

GDmac commented 12 years ago

That was a late-nite post (unwise). What happened was: the next() ran fine on my local machine (5.3.x), gave a error on the server (5.2.x). The find() issue is me just having to work/play more with QueryPath/JQuery :-)

GDmac commented 12 years ago

Solution for the xmlns:media issue, just putting it here for reference and documentation purposes.

Problem: when not defining the xmlns:media namespace in the item_stub, QueryPath exits with a fatal error: namespace not defined.

Solution: define the namespace in the item_stub too After inserting the items into the rss_stub, on outputting the xml, it seems the library is smart enough and removes the xmlns:media namespace definition from the individual <item> nodes.

        $rss_stub = '<?xml version="1.0" encoding="utf-8"?>
        <rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">
        <channel>
        <title></title>
        <link></link>
        <description></description>
        </channel>
        </rss>';

        $rss_item_stub = '<?xml version="1.0" encoding="utf-8"?>
        <item xmlns:media="http://search.yahoo.com/mrss/">
          <title></title>
          <link></link>
          <description></description>
          <category>image</category>
          <guid isPermaLink="false"></guid>
          <pubDate></pubDate>
          <media:content medium="image"></media:content>
        </item>';

        // prepare the rss. the closing parent() returns it set on the <channel> node
        $qp_rss = qp($rss_stub, 'title', $qp_rss_options)
          ->text('This is the title')
          ->next('link')->text('http://example.com')
          ->next('description')->text('foobar')
          ->parent();

        // fill an item
        $qp_item = qp($rss_item_stub, 'title')
          ->text('item title')
          ->next('link')->text('item-link')
          ->next('description')->text('etc.etc.')
          ->next('media|content')
             ->attr('url', 'attribute-value')
             ->attr('another', 'attribute-value');

        // add it to the rss stub (which is still on <channel>) 
        $qp_rss->append( $qp_item->top() );

        // output the rss feed
        $qp->writeXML();

/* Resulting XML
<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
  <channel>
    <title>Some title</title>
    <link>Some link</link>
    <description>Some description</description>
    <item>
      <title>Item title</title>
      <link>Item link</link>
      <description>Item description</description>
      <media:content medium="image" url="item-url" attribute="value" />
    </item>
  </channel>
</rss>
*/
technosophos commented 12 years ago

Thanks for posting the solution! I just noticed it.