Yii Framework Forum: Body classes based on URL - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Body classes based on URL Rate Topic: -----

#1 User is offline   artificial 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 96
  • Joined: 11-December 10
  • Location:Sydney, Australia

Posted 15 February 2012 - 03:16 AM

A bit of forewarning, I'm a relative newcomer to Yii and hence not sure if something like this already exists, whether it be an extension or even part of the core - if it is, please let me know.

I come from a bit of a Drupal background, and I really like hey they add classes to your body tag based on the page you're visiting. For instance, if you're on a page with URI /page/episode/01, your body tag may look like:

<body class="html not-front not-logged-in no-sidebars page-episode page-episode- page-episode-01 episode" >


It lets you effectively style different views, content types, etc. individually all from the one stylesheet without effecting different components. I had a quick search for something in Yii, but unable to find something, quickly threw something together.

In protected/components/controller.php, add:

	/**
	 * @var string the classes that should be displayed in the body element of each page.
	 */
	public $classes;

	/**
	 * Make sure we run the parent's constructor method, and call the function to calculate
	 * what classes to use.
	 */
	public function  __construct($id,$module=null) {
		parent::__construct($id, $module);
		$this->getBodyClasses();
	}

	/** 
	 * For easier styling, let's insert some classes from the URI in to our body element
	 */
	public function getBodyClasses() {
		if (! empty(Yii::app()->baseUrl)) {
			$uri = explode(Yii::app()->baseUrl, Yii::app()->request->requestUri);
			unset($uri[0]);
			$components = explode("/", implode(Yii::app()->baseUrl, $uri));
		}
		else {
			$components = explode("/", Yii::app()->request->requestUri);
		}

		foreach ($components as $id => $component) {
			if (empty($component)) {
				unset($components[$id]);
			}
		}
		ksort($components);

		$class = '';
		for ($x = 1; $x <= sizeOf($components); $x++) {
			if ($x <> 1) {
				$class .= '-';
			}
			$class .= $components[$x];
			$classes[] = strip_tags($class);
		}

		if (isset($classes)) {
			$this->classes = implode(' ', $classes);
		}
	}


And then in your layout view just add:
<body class="<?php echo isset($this->classes) ? $this->classes : '' ?>">


And then if you were on:
example.com/forum/example/news/welcome-topic-1

Your body tag would look like:
<body class="forum forum-example forum-example-news forum-mixxi-news-welcome-mixxi-1">

Allowing you to style elements on the forum, or for that particular parent forum (and child forum), or even the topic if you wanted.


Again, if anybody can think of a more efficient way, please let me know.
Alex Berriman
www.fishvision.com
1

#2 User is offline   Nick Mathew 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 1
  • Joined: 29-February 12
  • Location:http://nm7.org

Posted 29 February 2012 - 06:20 AM

Hi artificial, I like that Drupal adds classes to the body tag that are extremely useful for theming.
In fact, most people accuse Drupal of 'classitis' - the habit of adding multiple classes to every tag!

I made a few modifications to your code.

Modify the layout view, so that it includes a class on the front/home page too.
<body class="<?php echo isset($this->classes) ? $this->classes : 'front' ?>">


I also made a modification to the generation of $components
       
        /**
         * For easier styling, let's insert some classes from the URI in to our body element
         */
        public function getBodyClasses() {
                if (! empty(Yii::app()->baseUrl))
                {
                        $uri = explode(Yii::app()->baseUrl, Yii::app()->request->requestUri);
                        unset($uri[0]);
                        $pattern = '/[:\/?=]/';
                        $standardDelimiter = ':';
                        $string = implode(Yii::app()->baseUrl, $uri);
                        // replace delimiters with standard delimiter, also removing redundant delimiters
                        $string = preg_replace(array($pattern, "/{$standardDelimiter}+/s"), $standardDelimiter, $string);
                        $components = explode($standardDelimiter, $string);
                }
                else
                /*
                 * Rest of the code
                 */


This way, if you were on
example.com/site/page?view=about

your body tag would be
<body class="site site-page site-page-view site-page-view-about">


rather than
<body class="site site-page?view-about">

3

#3 User is offline   acorncom 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 100
  • Joined: 25-February 11
  • Location:CO, USA

Posted 29 February 2012 - 07:54 PM

Hey guys,
I found this really useful, so I turned it into a behavior. More details on my GitHub page:
https://github.com/a...dyClassBehavior

I was going to add it as an extension, but I don't have enough posts on the forum to allow me to do that yet :-/ I'll put it up at some point ...

Oh, and thanks for the code!
1

#4 User is offline   artificial 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 96
  • Joined: 11-December 10
  • Location:Sydney, Australia

Posted 29 February 2012 - 10:40 PM

@Nick
I'm glad that someone found it useful. I'll soon update my original post with your amendments (and of course give you credit) in case anybody else wants to take that approach. I actually never bother with that URL structure which explains why I overlooked it :P

@fr0d0z
It looks great. I'll take a look when I get home and if it all works I'll throw a link at the top of my post, as it's obviously a better way to go about it.
Alex Berriman
www.fishvision.com
0

#5 User is offline   KingYes 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 5
  • Joined: 28-January 12
  • Location:Israel

Posted 05 June 2014 - 01:01 AM

I just write better ext for this task. You can see the code there: http://www.yiiframew...i-body-classes/

Nice idea :)
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users