Showing posts with label Theming. Show all posts
Showing posts with label Theming. Show all posts

Saturday, December 2, 2017

Dealing with global web assets on Django

Dealing with global web assets on Django, my thoughts.

Working with Django, often your default mode of thought is apps. App are like these small self-contain programs that have their own urls, views, templates and the web assets that come with templates. Web assets, I mean those css (or Sass or Less files), images and maybe some JavaScript.

But when you start thinking long term, as far as templates go, apps will prove unmanageable. You'll start thinking of breaking then into smaller reusable units while leveraging template inheritance. Which leads us to the dilemma, how do we handle the global web assets?

My first idea was just put it on the /static folder. It works but not a good idea because a standard django .gitignore will exclude the /static folder.  Another thing, /static folder is where the django-admin collectstatic command puts all files it gets from the your dependency modules. It's not uncommon to have hundreds of MB inside this folder - hence, you don't commit them into repos.

So, I had to figure out a way that allowed to me get around the .gitignore rule (which I won't edit - they are standard for a reason) with the assets. What I ended up with is

1. Putting the global, shared web assets in an /assets folder
2. Inside the /assets folder are subfolders for css, js, img, font
3. Change my django configuration to handle it.


STATIC_ROOT = str(ROOT_DIR('static'))

STATICFILES_DIRS = [
    ('projectA1', str(ROOT_DIR('assets'))),
]

STATICFILES_FINDERS = [
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
]


The ROOT_DIR function is just a helper function that prints out the path to static relative to the root directory.

So anyway, an example usage then is like .. href="{% static "projectA1/css/style.css" %}" which is pretty nice. Details are here.

Monday, January 26, 2015

Dropping Bootstrap for Patternfly

Bootstrap is a godsend to single developers who suck at design. It had everything from components to simple animations for that eye candy.

And then things messy when that developer finds "themes" for bootstrap like the free ones over that bootswatch or the high-end stuff over at wrapbootstrap. I'm not saying these things are bad but all to often developers don't have the "design disciple" to use these themes. As developers, we have this tendency to use all the features, colors, suggested layout, etc.; user experience not withstanding. I'm guilty of this. We end up with this "soup" of a website or web app that's full of fancy animations and inconsistent visual design.

I think the fix for this is a set of guidelines that developers can happily follow and this is where patternfly comes in. Pattenfly is built on bootstrap so developers already using bootstrap will have no problem using it.

The nice things with Patternfly:

  1. No more trawling the net for lay-outing advice (https://www.patternfly.org/wikis/layout-templates/)
  2. Common design patterns done (https://www.patternfly.org/wikis/patterns/loginlogout/)
  3. Shitload of widgets, visual widgets and fonts
  4. And it's free; github here.




Sunday, August 18, 2013

Bootstrap tabs and the curious case of the missing bottom border

I'm a big fan of Twitter bootstrap. It's a big help for the design impaired. But as helpful Bootstrap is it still has a few things that you have to do yourself. It is where my story begins. I needed to get to here:

Tabs pulled right with an H4 element on the left WITH a bottom border


From here. This is how it should look like with the default markup using Bootstrap.

Tabs pulled right with an H4 element on the left WITHOUT a bottom border

I will post the markup here. The HTML markup is pretty standard.

     <div class="col-8 subheader">  
       <h4 class="pull-left">Postings</h4>  
       <ul class="nav nav-tabs pull-right" id="myTab">  
         <li><a href="#interesting" data-toggle="tab">Interesting</a></li>  
         <li><a href="#freshest" data-toggle="tab">Freshest</a></li>  
         <li><a href="#popular" data-toggle="tab">Popular</a></li>  
       </ul>   
     </div> 

The interesting part is getting the bottom border to work out. If all goes to plan it should stretch from the "Postings" element up to the first tab. My solution isn't that good if you're into strict semantic HTML5 but I'd rather get it working than worrying about writing proper semantic HTML5. At least it will validate.
     
     <div class="col-8 subheader">  
       <div id="btm-border"></div>
       <h4 class="pull-left">Postings</h4>  
       <ul class="nav nav-tabs pull-right" id="myTab">  
         <li><a href="#interesting" data-toggle="tab">Interesting</a></li>  
         <li><a href="#freshest" data-toggle="tab">Freshest</a></li>  
         <li><a href="#popular" data-toggle="tab">Popular</a></li>  
       </ul>   
     </div> 

The other half is the CSS rule. I write CSS using Less. Why? BECAUSE REASONS!

.subheader{
    position: relative;

    #btm-border{
        border-bottom: 1px solid #ddd;
        position: absolute;
        width: 446px;
        top: 42px;
    }
}

Wednesday, May 22, 2013

Android and the case of making app assets

ActionBarSherlock
Let's face it's fun to visualize and design Android apps at first then it goes down hill from there. I mean creating all them icons, gradient backgrounds and other assets is boring and sometimes down right tedious. And you have to it 3 times! So why not use a generator?

I have been using this website for a couple of projects: Android Assets Studio.

I'm a big fan of Roboguice (my blog entry) and the ActionBarSherlock which the Android Assets Studio complements. Using the studio allows me to generate the nine patch assets plus associated XML drawables and styles which I then copy straight into my project.

It's also nice that Studio has a bunch of icon generators. I especially find the generic icons pretty hand.

Saturday, April 13, 2013

You're a lazy bastard making a website and you need image placeholders

Yes, you read the title right.

How many times I have needed image placeholder while building website then get hit by lazy. I don't want to be creating image placeholders in Photoshop or Fireworks.

So, Google the Internet to find a service and it did not disappoint: http://placehold.it/

I hope this site stays online. I'm too lazy to find another one.

Tuesday, March 12, 2013

Timed redirect without the php, javascript fuzz

Having worked on a few MVC projects in different languages like PHP, C# and Java, there always that "thank you" or "success" page you show after successful operation like an insert or update. Often these pages are automatically redirected to some URL after a set amount of time, normally 10 - 15 seconds. Normally, I use javascript; Something like this:

 <script type="text/JavaScript">  
 <!--  
 setTimeout("location.href = 'http://google.com';",1000);  
 -->  
 </script>  

It works but then I found out there's an easier way to do this via a HTML meta tag. Wikipedia explains it here. This one just automatically redirects you to google.com after 10 seconds.

<meta http-equiv="refresh" content="10;URL='http://google.com/'">  

It does have drawbacks but it works and I don't have to really concern myself if the browser's javascript is on or off.

Tuesday, March 5, 2013

Tapestry 5.3 and the case of Twitter-Bootstrap disabled attributes

Making Tapestry5 use Twitter-Bootstrap as its style is quite easy but not everything is as it seems.

Bootstrap as some nice form style rules. It's quite easy to add them into normal tapestry5 common components. Like if you need some a textfield to look like a "search-query" field then you would write something like:

// Rounded corners
<input t:type="textfield" t:id="keyword" class="search-query" placeholder="Callslip ID"/>  

or if you need a page or event link to look like a button:

// Tapestry5 eventlink styled as a button via Bootstrap
<a t:type="eventlink" t:event="add" class="btn brn-primary" href="#">Add 1</a>  

But I have recently came across a scenario where I need to display a textfield with data that's by default is uneditable but under certain conditions can be edited. Reading the bootstrap documentation, you have to do something like this:

// As shown in the Bootstrap documentation
<input class="input-xlarge" id="disabledInput" type="text" placeholder="Disabled input here..." disabled>

OK, that should be easy to convert into tapestry5 component and use javascript to enable or disable the field. When done via jquery, removeAttr() or prop(). There's an equivalent to add an attribute.

// Tapestry5 is not happy about disabled attribute
<input class="input-xlarge" id="disabledInput" t:type="textfield" placeholder="Disabled input here..." disabled>

And that's this is where the problem crops up. Tapestry5 doesn't like any unpaired attributes. I'm talking about the disabled attribute at the end of the input element above. Fortunately, Peter Wendorff in the Tapestry mailing-list pointed me to a html microsyntax spec document explaining this unique nuance of html. You have to do a disabled="true" attribute to makeTapestry5 happy.

// How Tapestry5 wants it done
<input disabled="true" class="input-xlarge" t:id="name" t:type="textfield" placeholder="${name}" />
Other ways to write this doesn't work, even if the spec doc says its OK.

  • disabled="" -> doesn't work
  • disabled="disabled" or disabled='disabled' or disabled=disalbed -> also doesn't work
  • disabled -> obviously doesn't work

Wednesday, November 28, 2012

Multiple hyperlinks on an area (or image)

slicing + absolute positioning
I was working on a website which had a front banner that looked like a spice cup board and the owners wanted when you click on a certain "jar" it takes you to a certain page in the site. But they already had someone working on this before me and decided to use image slices + absolute positioning.

I'm not saying its a bad solution, I just don't like dealing with multiple images and other penalties (ie. maintenance) associated with it. I would rather go with a single large image and define regions in it that's clickable. That's where image maps come in.

Image maps enable me to define multiple links within a single image. It's clean and doesn't involve any JavaScript or CSS just plain HTML5 markup.

You start off by declaring the image:

<img scr="bigbanner.jpg" alt="frontpage banner" border=0 usemap="#hotspots"/>  

The new thing here is the usemap attribute. The value of the usemap attribute must be the same with the map id. The map element acts as a container for specifications regarding the map's active areas (ie. hotspots), where are define as area elements within the map.

 The matching map markup would be:

<map name="hotspots">  
      <area shape="rect" coords="20,20,170,170" href="somepage2.html"/>  
      <area shape="circle" coords="250,175,50" href="somepage3.html"/>  
      <area shape="poly" coords="117,241,277,312,84,370" href="somepage4.html"/>  
 </map>  

The shape of the area element is influenced by the *duh* shape attribute. Rectangles and circles are fairly easy to use but watch out for with poly. Its the most flexible and most tricky to use. In the example, I'm creating a "triangle"; the first 2 values in the coords form the first point, the second 2, form the second point and the third pair gives use the third (end) point. Given enough coords information, I can make the "poly" area follow the outline of any item on any image.

As for the coordinate values, I just have to remember that the top left corner of the image is 0,0. Also, map is a non-visual element so I can put it anywhere on the page markup.

Sunday, September 2, 2012

Quick & Dirty Tabs on Drupal nodes

I just want a dead simple tab on a Drupal node but sometimes Drupal (with the internet) will just bend you over and spank you.

If you are reading this, I bet you found Quicktabs and read katbailey's "Go forth and tabbify" post but you came to the conclusion that its either:
  1. To complicated; You suspect that the hook_page_alter() function is gonna bite you in the ass down the line 
  2. Its not what you need 
I'll also bet you tried a few other approaches like leveraging the jQueryUI tabs like what Matt did and still found that it wasn't what you want. So now what? Well, you can do what I did - the quick and dirty tabs. 

My quick and dirty tabs is just javascript, html markup and a Omega subtheme. And it just involves 4 steps.

1. The HTML markup. You will use this inside your node.tpl.php or equivalent node template override. Notice the page-control and page-sections parts of the markup.
<div class="com-profile">  
      <div class="page-control">  
           <ul class="myQDtabs">  
                <li class="active"><a href="#">Basic Information</a></li>  
                <li><a href="#">Photos</a></li>  
                <li><a href="#">Forum</a></li>  
                <li><a href="#">Contact Persons</a></li>  
           </ul>  
      </div>  
      <div class="page-sections" style="display:none" >  
           <div class="section">  
                <div class="info">  
                     ...  
                </div>  
           </div>  
           <div class="section" style="display:none" >  
                <div class="gallery">  
                     ...  
                </div>  
           </div>  
           <div class="section" style="display:none" >  
                <div class="forum">  
                     ...  
                </div>  
           </div>  
           <div class="section" style="display:none" >  
                <div class="contactperson">  
                     ....  
                </div>  
           </div>  
      </div>  
 </div>  

2. The Stylesheet. I settled on a pill type of tabs. Just add these styles on the main subtheme stylesheet.
3. The Javascript. This is a tricky bit. If you have read Matt's post about Drupal and jQueryUI tabs, you'll know that Drupal allows other javascript frameworks so Drupal uses jQuery's .noConflict() function. This forces you to write your jQuery withouth that the '$' alias. Oh, create this script somewhere inside your subtheme.
jQuery(document).ready(function(){
    QDtabs('.myQDtabs','.page-sections','click');
});

//function-type tab switching
QDtabs = function($tabs,$tabcontent,method){
  jQuery($tabcontent + ' .section').eq(0).fadeIn();
  jQuery($tabs + ' li').eq(0).addClass('active');
 
  jQuery($tabs + ' li:not(.active)').die().live(method,function(e){
  e.stopPropagation();
  
  var $self = jQuery(this);
  var index = $self.index();  
  $self.addClass('active').siblings('.active').removeClass();  
  jQuery($tabcontent + ' .section').hide().eq(index).stop(false,true).fadeIn();
  
  return false;
 })
}

4. And the last step is making my Omega subtheme load the custom script. Omega has a particular way of adding custom javascripts.

libraries[my_script][name] = QD custom script
libraries[my_script][description] = Quick and dirty tabs
libraries[my_script][js][0][file] = my_scripts.js
libraries[my_script][js][0][options][weight] = 15

The last thing to do is a bit of housekeeping - Clear your Drupal cache and turning on my_script inside my theme's admin interface.


Monday, April 23, 2012

My website starterkit - 1kb Grid, Less, Formalize & Reset

I made starter kit for web development. It's a simple 960 grid-based kit with Less CSS. My starter kit is based on Tyler Tates' 1KB CSS grid, but it also has other stylesheets like:
  1. Meyer's Reset - to reset everything
  2. Formalize - for well mannered forms. 
  3. Style.less - This is where you should be adding your CSS, in the Less format.
I also turned Formalize and Grid into Less style sheets so I can combine all three into a single style sheet.

The starter kit also has jquery1.7 (via CDN) already added. You might want to change this during development.

To get the most of my starter kit you'll need something to turn Less style sheets to valid cascading style sheets. Try out Winless or Simpless.

You can clone my mercurial repo at https://bitbucket.org/jaypax/grid10kless if you want to try it out.

In case your wondering the code is DBAD licensed.

Saturday, January 28, 2012

That jquery click event and moving viewport problem

Sometimes certain combinations of attributes and values on a DOM element conspire to make you look stupid. In this case, a jQuery click function attached to an anchor tag with a href attribute.
<a href="#" class="reply-action">  
      <span>  
         <i></i>  
             Reply  
         </span>  
      </a>  
</span> 
And the jQuery is pretty straight-forward. The anchor tag when clicked will just toggle a div.replies to show or hide.
$('.reply-action').click(function () {
 $('.replies').toggle();
})
At this point, all things work. The replies div slide up and down as described by the jQuery toggle function. Normally this isn't a problem when you run this code at very top of the browser viewport. "Top of the browser viewport" simply means that the page hasn't scrolled down. The "moving viewport" problem happens when you run the click function when you're at bottom of the page. The click function keeps forcing the viewport to move to the top. Its annoying as hell. Fortunately the solution is simple. So simple in fact it made me go *FACE PALM*. The root of the problem is the the anchor href attribute set to "#". So by just changing the href attribute to something else like javascript:void(0) or just simply delete it, you fix the problem.
<a href="javascript:void(0)" class="reply-action">  
      <span>  
         <i></i>  
             Reply  
         </span>  
      </a>  
</span> 
It took me about a day to figure it out after trying to use overly complex jQuery like event and mouse APIs. Talk about being given the runaround.

Tuesday, November 29, 2011

Centering an inner div vertically inside another div

Green div is centered on a gray div
So how do you:
A div tagged as "divsmall" is contained inside a bigger div tagged as "divbig". the challenge is how to *vertically* align/center divsmall inside divbig.
Interesting question although having limited applications but still this should be possible. So, broke out my favorite IDE and started coding away. We start with our HTML.

 <!DOCTYPE html>  
 <html>  
   <head>  
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
     <link rel="stylesheet" type="text/css" href="css/mystyle.css"/>  
     <title></title>  
   </head>  
   <body>  
     <div class="div-big">  
       <div class="div-small">  
         <strong>div-small</strong>  
       </div>  
     </div>  
   </body>  
 </html>  
This should be easy to read. We then move to the CSS.

.div-big{
    background: #999;
    border: 1px solid #000;
    min-height: 640px;
    margin: auto;
    text-align: center;
    width: 940px;
}

.div-small{
    background: #66cc00;
    border: 1px solid #666;
    min-height: 600px;
    margin: 20px auto;
    width: 25%;
}
The trick in the margins. If you look at line 14, that all you need to center inner div. The width doesn't really matter. Try modifying the width value at line 15. The div should adjust in relation to its parent div.

Monday, November 7, 2011

Views and jCarousel fun

Node.tpl.php
So, to make a long story short, I got a client who wanted to display his Drupal site's content nodes just like the image above. We are working with Drupal 6.

He wanted:
  1. A callout box that contains location and a link
  2. An image carousel 
  3. A social networking toolbox 
Interesting. 

So we start off with a custom content type. My setup is composed of CCK, Location, Image, ImageCache. 

Content Construction Kit (CCK) needs no explaination. You can't make custom content type without it. The Location module is used with CCK to capture Location data. The Image module so we can attached, well, images to the node. The ImageCache complements this; allowing us to process the attached images to whatever size we need it.

We are are off to writing code in the our theme's template.php. We are going to preprocess our node data. Here is mine. Your CCK field names might not be same as mine but you can look at the CCK field names up with a dpm($vars) call. Remember that you can't make a dpm call without the devel module.

function [YOUR_THEME]_preprocess_node(&$vars, $hook) {      
    // construct callout box for organizer and venue
    $organizer_url = $vars['field_organizer_link']['0']['view'];  
    $venue_name = $vars['field_record_venue']['0']['name'];  
    $venue_street = $vars['field_record_venue']['0']['street'];  
    $venue_city = $vars['field_record_venue']['0']['city'];  

    $field_venue = '<div class="venue"><span class="venue-title">' . $venue_name . '</span><br/> <span class="venue-location">' . $venue_street . ', ' . $venue_city . '</span></div>';  
    $field_organizer = '<span class="organizer"><p> For more Information,<br/> visit the organizer\'s site</p>' . $organizer_url . '</span>';  
    $vars['callout'] = '<div class="callout">' . $field_venue . $field_organizer . '</div>';  

    // construct embedded view for image carousel  
    $embedded_view = 'embedded_related_img';  
    $embedded_args = $vars[nid];  
    $emdedded_view_display = 'default';  
    $vars['embedded_carousel'] = views_embed_view($embedded_view, $emdedded_view_display, $embedded_args);  
  }  
We then can insert the newly constructed callout box via the $callout variable. See line #12.

The next step here is the image carousel. I did this using Views and jCarousel. When you read up on how to use jCarousel it should be apparent that you can use a Views argument to make an image carousel of the current node using its id and get all the attached images. I then named the view "embedded_related_img". Set the view style to jCarousel. The options shouldn't be a problem. It will not preview correctly since Views will not load the javascript for the carousel. I then attached this on the node via the $embedded_carousel variable. The magic is the views_embed_view() function. See lines #15 - 18.

And as for the social networking bar that's done with the addThis module. This should be a no-brainer.

For reference, here is the node.tpl.php file.

<div id="record-<?php print $node->nid; ?>" class="node record clear-block">   
   <?php if ($page == 0): ?>  
     <h2 class="title"><a href="<?php print $node_url ?>" title="<?php print $title ?>"><?php print $title ?></a></h2>  
   <?php else: ?>  
     <h2 class="title"><?php print $title ?></h2>  
   <?php endif; ?>  
   <div class="content clear-block">  
     <?php print $picture ?>  
     <?php if(!$teaser): ?>  
       <?php print $callout; ?>  
     <?php endif; ?>  
     <?php print $content ?>  
   </div>  
   <?php if(!$teaser): ?>  
     <div class="embeded_view clear-block">  
       <?php print $embedded_carousel; ?>  
     </div>    
   <?php endif; ?>  
   <?php  
   if ($links) {  
     print '<div class="node-links">'. $links .'</div>';  
   }  
   ?>  
 </div>

Saturday, November 5, 2011

Overcoming CSS's limitations with Less CSS

I have written my fair share of CSS for almost every kind of project. CSS is easy to use but on a whole I always wished that CSS had some kind of programming elements. You dont' how many times I have come across a scenario where I had to write a style rule over and over again or target specific children classes inside a parent element. The resulting CSS is not pretty. This was until I came across Bootstrap from Twitter and Less CSS. The tag line says:
LESS extends CSS with dynamic behavior such as variables, mixins, operations and functions. LESS runs on both the client-side (IE 6+, Webkit, Firefox) and server-side, with Node.js.
Yes, CSS with "dynamic behavior" and everything still boils down to pure CSS. You just drop in less.js and off you go. Here's an examples that I think makes writing CSS interesting again. Supposed that you have a hex colors that is used all over the place, this wouldn't be a problem until you have change it. Now you can crank up your editor's Find and Replace but we know that sometimes that thing replaces values that it shouldn't be replacing. So....
/* Less CSS sheet */
@color: #4D926F;

#header {
  color: @color;
}
h2 {
  color: @color;
}

The variables @color allow me to specify widely used values in a single place, and then re-use them throughout the style sheet, making global changes as easy as changing one line of code. With a little foresight, I can set this up so what I change say only affects #header divs or certain areas in my HTML page. Don't worry because, when you pass the site to the browser, your Less CSS will be "compiled" by the less.js spitting out pure, clean CSS.
/* Your CSS as far as the browser is concern */
#header {
  color: #4D926F;
}
h2 {
  color: #4D926F;
}

I think this will become another important tool in a web developers toolbox. I already use it indirectly anyway. I'm a big fan of the Bootstrap framework from Twitter.

Monday, October 31, 2011

Adding unique CSS classes to primary menu elements

Adding unique CSS classes to primary menu elements in a Drupal theme is quite easy. You just need to override the theme_menu_link function in the template.php.

I'm working on a Fusion sub-theme named nebula. So the function is named nebula_menu_link .
/**
 * Manually add unique CSS classes to primary menu li elements
 * @staticvar int $item_id
 * @param type $variables
 * @return type 
 */
function nebula_menu_link($variables) {
  $element = $variables['element'];

  static $item_id = 0;
  $element['#attributes']['class'][] = 'nv_' . (++$item_id);
  $sub_menu = $element['#below'] ? drupal_render($element['#below']) : '';

  $output = l($element['#title'], $element['#href'], $element['#localized_options']);

  return '' . $output . $sub_menu . '';
}

Refer to line #11 that's where the meat of the function. The line adds a "nv_1" class to the first primary menu element. It should be easy to figure out that the succeeding elements would be "nv_2", "nv_3". That's the (++$item_id).

Here's how it would look when theme renders.
<ul class="menu">
      <li class="first leaf nv_1">
          <a href="/" class="active">Home</a>
      </li>
      <li class="leaf nv_2">
          <a href="/content/about-us" title="">About Us</a>
      </li>
      <li class="leaf nv_3">
          <a href="/content/solutions" title="">Solutions</a>
      </li>
      <li class="leaf nv_4">
          <a href="/content/services">Services</a>
      </li>
      <li class="leaf nv_5">
          <a href="/" title="" class="active">News</a>
      </li>
      <li class="leaf nv_6">
          <a href="/" title="" class="active">Library</a>
      </li>
      <li class="last leaf nv_7">
          <a href="/content/contact-us" title="">Contact</a>
      </li>
  </ul>

Now we can target individual li elements of the primary menu. Theme away!

Sunday, August 28, 2011

Drupal Themes and Favicons

A favicon also known as a shortcut icon, Web site icon, URL icon, or bookmark icon, is a file containing one or more small icons, most commonly 16×16 pixels, associated with a particular Web site or Web page. Its that small image that you see on you Firefox tab along with the name of the webpage.

Clients like favicons but making one can be easy or hard, it depends on your approach. If you're old school, then you can use MS-Paint or GIMP or if you're like me,I cheat. I use a web favicon generator. I use favicon.ico generator. Most amazing thing about favicon.cc is that its free. FREE!

You have a favicon, you'll need to copy it to your theme folder. Make sure that is on the same folder as your .info file. Don't put in a sub folder like say img or css.

You'll need to edit your theme .info file. Here is a excerpt of mine theme .info file.

; ------- Declare default theme information

name        = LGR 960.gs
description = Omega Sub-Theme for LGR
screenshot = screenshot.png
core       = 6.x
base theme = omega

; ------- Declare default theme features
features[] = logo
features[] = name
features[] = slogan
features[] = mission
features[] = node_user_picture
features[] = comment_user_picture
features[] = search
features[] = favicon
features[] = primary_links
features[] = secondary_links

The thing here is the theme features section where it says feature[] = favicon. This basically says to Drupal to look for your favicon on the same level folder where the .info is placed and use it. Normally, this is automatic to Drupal themes especially if you subtheme one of its many primary themes like Zen or Omega.


Tuesday, May 17, 2011

Rounded Corners in Drupal - the easy way

Doing rounded corners is pie in Drupal. There's really 3 "real" options.
  1. Do it with a module (http://drupal.org/project/rounded_corners)
  2. Do it with hardcore CSS + images
  3. Do it with jQuery
I don't know about you but options 1 and 2 take too much work (for me anyway). So, I went option 3 and let jQuery do all the work.

You start off by downloading the jQuery corner plugin. This is a sweet little plugin written by Dave Methvin and Mike Alsup. After downloading the corner plugin, copy it to into the /js folder of your target theme. Create the folder if it doesn't exist.

Refer to the screenshot to the right. If you are wondering, I am using Netbeans 7 and that is a partial screenshot of my workspace.

After that create a second js file. I named by icc960scripts.js. This is where I wrote the javascript to use the jquery corner plugin. Here is the content in mine:

$(document).ready( function(){

    // the top part of the block
    $('#sidebar-last .block h2, #header-regions .block h2, #main-content .odd h2').corner("top");

    // the bottom part of the block
    $('#sidebar-last .block .content, #header-regions .block .content, #main-content .node-content ').corner("bottom");

});

Top part of the block is an H2 element which is rounded only on the top part. And then bottom part is a
DIV element with a border. You might have to override (or modify) the node.tpl.php template if you are using a template with a different markup.
Screenshot from firebug of the HTML structure
Rounded Block
What left is just to add some CSS to make it look good. Here's how mine turned out. The header background color is #CBB859 and the border value of the div is 1px solid #ccc.

BTW, don't forget to declare the scripts in the .info file of your Drupal theme.

; ------- Declare default javascript includes
scripts[] = js/jquery.corner.js
scripts[] = js/icc960scripts.js

It should be easy to figure out that the same technique can be applied to other elements in the Drupal theme output. Experiment and see what works and what doesn't!