tags:

views:

134

answers:

3

idea

Via jQuery, I was able to mark all :first-child and :last-child elements in document (well, almost all :)) with class first which could I later style (i.e. first li in ul#navigation would be easily adressable as ul#navigation .first).

I used following code:

  var $f = $('*:first-child')
      $f.addClass('first');
  var $l = $('body *:last-child')
      $l.addClass('last');

example

http://jsbin.com/ikuca/3

Example is already here - it's not the way to do it however, it's just an idea prototyped in other, for me at the moment easier language.

question

Now, my question is if it's possible to do the same via php, so non-JS users/gadgets could have the same effects and additional styling and also it would be less overkill on browser.

So, is it possible to capture output, parse it as html and inject this class easily in php?

clarification

I'm quite aware of output buffering, just haven't done much stuff with it - also, i'm not sure about modificating output string in php as parsed dom (without regex) - and how tough on server it'll be - with caching of course, so this whole stuff will run once until the page will be edited again.

+3  A: 

I'm sure you could use output buffering to capture your assembled PHP page and then use DOM and XPath on it to add the class attributes, but the question is, why don't you just put the classes onto the elements when assembling the page in the first place? Saves you the jQuery and the capturing.

Also, adding the CSS classes with jQuery to be able to do ul#navigation.first is somewhat odd too, because the jQuery expression you used is a CSS selector, so you could use it directly to style the first child from your CSS file. The only reason to add a class .first is if you want to be backwards compatible with browsers unable to process :first-child.

Gordon
Was just typing mostly the same stuff - +1
Andy E
because this is in it's way *simpler*? it's like cross-browser :first-child
Adam Kiss
@Adam no it's not. In fact, it is totally complicated. Add the classes in the first place and you don't even need the jquery anymore.
Gordon
@Gordon is right: the best way to do this is to add the classes in the first place!
Josh
@Gordon - using jQuery - it's just a quickly prototyped behavior in another language, so you'll get the idea quicker, please, see my edit.@Josh: well, that's what I'm trying to do...
Adam Kiss
@Adam I don't get the idea :) but if you want do it anyway, you do it like described above.
Gordon
@Adam: What Gordon is saying is, rather than using output buffering, find the actual `ul#navigation` in the PHP file and just make the first `li` have a class if "first".
Josh
@Gordon - of course you do :) I used jQuery, so you'll quickly see what I want to accomplish, rather than saying "I want *something* like *this*" @Josh - I got it... it *is* simple to find it in template and add it. but what about dynamic, multi class menus, modules and stuff... and if you do more than one site... Ah, you get the picture.
Adam Kiss
Anyway, it's probably that simple, thanks :)
Adam Kiss
A: 

I think you'll find it's easier to do this in jQuery than PHP, but it can be done in PHP.

To capture output you want output buffering, which you activate with the ob_start function, before sending any output. You can pass ob_start() a PHP function which will receive the HTML code as a parameter and can then manipulate the HTML using PHP's DOM functions.

Josh
So no harm done? just something like `dom_parse(ob_flush());`? what about server load, if I'll do it (with proper caching, of course)
Adam Kiss
Well, it's additional load because the server generates the HTML, and now has to parse it to change it. It would be best to add the classes when generating the HTML. If it's not a lot of HTML it won't cause too much load. And there are some claims that using output buffering actually makes your code run faster...
Josh
And as for `dom_parse(ob_flush());`, it should probably be `ob_start('dom_parse')`. Then when you call ob_end_flush(), your output buffer is sent to the dom_parse() function you defined. See the manual for `ob_start`
Josh
@Josh - That's just what I meant :]
Adam Kiss
A: 

jQuery runs in the client's borwser. PHP runs on the server. You can't modify the DOM in the browser from the server once it is served.

What you could do, is to serve the page already with the proper classes. For example in PHP when you print a table:

<table>
<?php
$i=0;
foreach ($rows as $row):
?>
    <tr class=<?php echo ($i%2==0?'even':'odd')?>
        <td><?php echo $row;</td> 
    </tr>
<?php
endforeach;
?>
</table>

ps. Do you really want to support clients without JS?

sibidiba
You can modify the HTML before sending it, however. With output buffering, for example. Or by just generating the proper HTML in the first place :-)
Josh
@sibidiba: Putting the obvious stuff aside (jQuery there, PHP here), lowering javascript severity on mobile devices could be plus.
Adam Kiss
And whole point of this is have some *basic* classes (first, last ...) ready without thinking about it - do xhtml, do css (with `first`) in mind, put the template system in and voila.
Adam Kiss