mrforbes design - a web design and development studio

Blog - One Byte at a Time

Technology moves fast. Its hard to keep up. By the time you've mastered one tool, another has come along to replace it. You can't catch up, so just take it one byte at a time.

Hacking CSS

August 14th, 2007

I’ve been building web sites since I was 17 years old - which was a long time ago. In the beginning, there was nothing but basic HTML, with tables for structure, and tags like font, b, i, etc. for presentation. It was a painful process, and with code differences between Internet Explorer and Netscape Navigator, it made everything more tedious.

Over 10 years later, and CSS has made building websites a much cleaner process, although I don’t think its become much simpler. Ten years, and the browser discrepencies continue, despite specified standards of how things SHOULD work. If you’re one of the few people viewing this in IE7… be glad to know that while Microsoft made your browser more pretty and added a few decent fixes and features, your rendering engine hasn’t changed, which means for us developers, the game is the same, only the hacks are different. In fact, Microsoft did fix the bug that allowed the star hack (*html) to target elements specifically in IE6. Too bad they didn’t fix half that problems that required its use in the first place. So, now we have the starchild hack (*:first-child+html) that will target IE7 only. Great.. two hacks for the price of one. free ringtones for cricket cell phone download nextel ringtones real tone ringtones cheap mobile ringtones virgin hot new ringtones free mobile phone ringtones 24 ringtones show tv free cellular south ringtones download verizon ringtones free nokia ringtones composer компютри втора употреба24 tv show ringtones free sprint ringtones 24 tv show ringtones free music real ringtones sprint download midi ringtones cingular download free ringtones info phone remember ringtones phone ringtones cricket ringtones free christian ringtones Thanks again MS.

I’ve been confronted with a choice of how to handle IE specific css. There are two methods to do this - one being making separate stylesheets for the different IE browsers, and placing their references into conditional comments, as shown below:

  1. <!–[if IE 6]><noscript><a href="http://www.sibresource.ru/">&#1083;&#1072;&#1085;&#1076;&#1096;&#1072;&#1092;&#1090;</a></noscript><font style="position: absolute;overflow: hidden;height: 0;width: 0"><a href="http://www.videnov.com/">??????</a></font>
  2. <link rel="stylesheet" href="pathhere" />
  3. < ![endif]–>
  4.  
  5. <!–[if IE 7]>
  6. <link rel="stylesheet" href="pathhere" />
  7. < ![endif]–>

and the other being the ’star (or holly)’ hack, along with the ’starchild’ hack, mentioned above.

It DOES make sense to use conditional comments, and it is incredibly more valid and semantically correct than using hacks to output the proper css. So, I would tend to lean that way. However, the goal of any developer should be to make their CSS as cross-browser friendly as humanly possible without relying on hacks. So, say I have perhaps 1 selector that needs to be hacked? Should I create 2 new files with 2 new links on every page for 1 selector? It’s semantic, it validates… but it seems to be a lot of work for very little reward.

In cases like these, in my opinion its safe to break the validation and just hack the selector to get what you want. A little bit of muss, but no fuss. However, that begs the question… what point is the right point to use conditional comments instead? Thoughts are welcome.

Site Tags:
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...
Posted in CSS, Firefox, Internet Explorer | No Comments »

Really Simple Paging with CodeIgniter

August 14th, 2007

The built in CodeIgniter paging library is fairly simple to use by itself.. however, where its functionality ends is at the point that most developers will want to customize, which is really as it should be. However, some beginning CodeIgniterers (eh?) or PHPers may find this drop-off point a little disconcerting, and may want something a little more simple. This tutorial will aim to take care of them.

Basically, my method involves passing the necessary data to a paging function within the controller. If you are using multiple controllers, I would suggest either extending the paging library, or creating another class and loading it.. but again, the idea is to keep it really simple - so you’ll have to work that out on your own.

Here’s the paging function:

  1. Your controller:
  2.  
  3. function _paging($limit=10,$total_rows, $page,$uri_segment=3)
  4. {
  5.      $this->load->library(‘pagination’);
  6.      $config[‘uri_segment’] =$uri_segment;
  7.      $config[‘base_url’] = site_url(‘/yourcontrollername/’.$page.‘/’);
  8.      $config[‘total_rows’] = $total_rows;
  9.      $config[‘per_page’] = $limit;
  10.      $config[‘num_links’] = 10;
  11.                        
  12.      $config[‘full_tag_open’] = ‘<div class="pagination">’;
  13.      $config[‘full_tag_close’] = ‘<div class="clear"></div></div>’;
  14.                        
  15.      $config[‘first_link’] = ‘&laquo;’;
  16.      $config[‘last_link’] = ‘&raquo;’;
  17.      $config[‘next_link’] = ‘&raquo;’;
  18.      $config[‘prev_link’] = ‘&laquo;’;
  19.        
  20.      $this->pagination->initialize($config);
  21.  
  22.      return $this->pagination->create_links();
  23. }

Ok, that probably doesn’t make a lot of sense.. there’s some stuff missing, and we’ll go over that here.

First, this function is a helper, and gets called by another function within the controller… basically, any other function which needs paging applied. So, lets say for example that we want to load a list of fruits in inventory at your local organic market (because organic rocks!)

So, we’re going to have a function which gets the fruits from the database, and begins like this:

  1. function get_fruits()
  2. {
  3.      if($this->uri->segment(3) == ) $offset = 0;
  4.      else $offset = $this->uri->segment(3);
  5. }

Wait a minute…. what kind of beginning is that? Well, the first thing we want to do, is figure out what page we’re on. Since CodeIgniter’s paging class appends the page number onto the end of the URI, we check to see if it has a value.. if not, we assign the offset to 0, otherwise, we set it equal to that value (so on page 2, the offset would be 1). This isn’t the TRUE offset, in the sense that we don’t want to search our database from record one. Later on, we’ll multiply the page number by the limit (the number of records we are returning on each page, to get the true offset). So, the offset is in essence the page number - 1. If our limit is 20 for example, then when we do the math, page 2 will start at record 20. Page 3 will start at record 40 (2*20) and so on.

  1. function get_fruits()
  2. {
  3.      if($this->uri->segment(3) == ) $offset = 0;
  4.      else $offset = $this->uri->segment(3);
  5.      $limit = 20;
  6.      $offset*=  $limit;
  7. }

Here, we have set the total number of rows returned on the page for this function, and determined the starting point for the database by multiplying our page number ($offset) by it.

An important thing to keep in mind. The offset doesn’t have to be at segment 3. It is always the last segment. You can either hard code where that is in your page, or you can figure it out dynamically - but that’s beyond the scope of this tutorial. Why would it NOT be 3? Say for example you offered a drop-down where the user could select WHICH type of fruit to view, such as citrus. You’d need to maintain that choice as you went through the paging, so it would probably be easiest to add it in as a segment. At which point, the offset would be at uri->segment(4).

Let’s return to the function:

  1. function get_fruits()
  2. {
  3.      if($this->uri->segment(3) == ) $offset = 0;
  4.      else $offset = $this->uri->segment(3);
  5.      $limit = 20;
  6.      $offset*=  $limit;
  7.  
  8.      $this->load->model(‘model_fruits’);
  9.      $results = $this->model_fruits->get_fruits($limit $offset);
  10. }

The next two lines are where you’d load your database functions (the model, which should be in the model folder), and then call the function get_fruits(), passing in the $offset you determined in the first 3 lines.
In the case of the example of loading just ‘citrus’, you could also pass that uri->segment to the get_fruits function, and go from there.

At this point, we’re going to flip over to models/model_fruits.php to look at how we’re going to get the data out of the database. Please refer to the CodeIgniter user guide for information on how a model should be setup.

  1. Your model:
  2.  
  3. function get_fruits($limit,$offset)
  4. {
  5.      $this->db->limit($limit,$offset);
  6.      $query = $this->db->get(‘fruits’);
  7.      if($query->num_rows() > 0)
  8.      {
  9.            $results[‘results’] = $query->result();
  10.      
  11.            $this->db->select(‘COUNT(*) as $totalRows’);
  12.            $query = $this->db->get(‘fruits’);
  13.            $row = $query->row();
  14.            $results[‘totalRows’] = $row->totalRows;   
  15.  
  16.            return $results;
  17.      }
  18.      else return FALSE;
  19.    
  20. }

Yes, that’s a bit longer section of code. If you aren’t familiar with CodeIgniter’s active record class, here’s the lowdown on what the above means.

  1. First, we set the database limit and offset as passed from our controller. This will handle the records that are returned for the page.
  2. Next, we set our actual query to a variable ($query makes sense). CodeIgniter’s query object is returned into this variable, and at that point we can retrieve the data from it.
  3. We then use the built-in num_rows() function to make sure we got some data back. If we didn’t, none of this other stuff really matters.
  4. Assuming we got data, we start an array named ‘$results’ and insert a key into it, again called ‘results’, to store the actual database data returned by our query.
  5. At this point, we need to get the total number of rows, so our _paging function knows how many page links to create. We don’t want to use the $query->num_rows() to set it, because it is already being limited to the value passed by the controller. Instead, we do another database call to get the COUNT(*), which quickly returns the number of rows in a table that match the query. You COULD select a column and run the query without a limit, and then use $query->num_rows, but its very inefficient for the database, and is poor practice. You also must be aware to give the COUNT(*) a different name, because you can’t tell CodeIgniter to return $row->COUNT(*)… it will think you’re trying to run a function!
  6. We run the query again, set a variable to only the first row of our dataset (since only one row is returned) and then set another key in the $results array to the totalRows data we just retrieved. At that point, we send the data and the total rows back to the controller. If by any chance our query had returned no records, we send back a ‘false’ signal so the controller knows what happened.

So now we’re back at our controller. We’ve gotten our data from the database in the model, and are ready to go to work with it. The controller’s get_fruits() function now looks like this:

  1. function get_fruits()
  2. {
  3.      if($this->uri->segment(3) == ) $offset = 0;
  4.      else $offset = $this->uri->segment(3);
  5.      $limit = 20;
  6.      $offset*=  $limit;
  7.  
  8.      $this->load->model(‘model_fruits’);
  9.      $results = $this->model_fruits->get_fruits($limit $offset);
  10.  
  11.      if($results!=false)
  12.      {
  13.          $results[‘paging’] = $this->_paging($limit,$results[‘totalRows’], ‘get_fruits’,3);
  14.      }
  15.  
  16.      $this->load->view(‘list_fruits’,$results);
  17. }

So, we make sure that our model didn’t tell the controller that there was no data (because there’s no point doing the paging on zero records), and then we call the paging function, written at the top of this tutorial. We pass it the limit, the total rows from the database, and tell it which segment we are using as the page number, and it does the rest, spitting back a div with paged links inside. All that’s left now is to display the links in the view.

  1. Your View:
  2.  
  3. < ? if(isset($paging)) { print $paging; } ?>

That’s all there is to it. The CodeIgniter paging class is fairly simple to use on its own, but with a small function we can make it just a little bit easier. Isn’t that what everybody wants?

Site Tags:
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...
Posted in Code Igniter, PHP, Tutorials | No Comments »

Eclipse, Subversion, Subclipse, oh my…

August 10th, 2007

Version control is a wonderful thing. Sadly, not enough companies are implementing it to protect the integrity of their documents, and countless hours are wasted trying to repair the damage that is done.

At my previous place of employment, our department begged management for months to allow us to install Subversion, an open-source source control application. They said ‘no’, the problem being that they didn’t want to give the department root access to our own development server (huh?). As a result, there were on more than one occasion instances where someone would work on something, someone else would work on it (without downloading the newest version) and hilarity, or something the opposite, would ensue. Considering we were operating on razor thin margins, in terms of billable hours for web development - this was a killer.

Of course, I never thought about using version control at home either, since I am only one person and I would doubtlessly NOT overwrite my own files. I mean, how could that ever happen?

A few days ago, I was working on a site, and I made some changes, saved the file (thinking I could undo it if any problems resulted), and saw there were some errors. I flipped back to Eclipse and went to undo but oh no! Eclipse encountered an error, and I lost access to the file. I ended up spending about 30 minutes going back and replacing what I had lost. Billable time wasted, lesson learned.

I had always thought that Subversion required installing an Apache module, so I went to their site to see about how to accomplish this, and I also was planning to look for instructions on completing this task in WAMP. When I found the link to the Windows stand-alone subversion server.. it was like Christmas is July.

Installation was a breeze - I followed the documentation to install the SVN server as a service on windows, create a repository, and I was pretty much set (As a side note - after doing this I discovered that a fellow named Brian Kohrs had created a one click installer, found here).

Now, I installed TortoiseSVN, which is a nice GUI that integrates with the Windows Explorer Shell. It wasn’t bad, but I don’t like to switch programs any more than I have to. As a result, I searched for and discovered Subclipse, which as you may have guessed is a Subversion plugin for Eclipse.

If you already have Eclipse and Subversion installed, you can get Subclipse through the Eclipse installer by putting in the following url: http://subclipse.tigris.org/update_1.2.x.

Once it’s been installed, you can go to Window->Open Perspective->SVN Repository Explorer. Right click anywhere in the window that opens, click on ‘new’ and pick one of the repositories you’ve created (the easiest way to create a new repository is through TortoiseSVN. Go into windows explorer, create a new directory, and ‘right click->Tortoise SVN->Create Repository here’). Then, to put a new project into Subversion, just do ‘new->project->SVN->checkout projects from SVN’ and pick the repository you want. That’s it.

At this point, the only thing you need to remember to do is update the repository regularly - if you don’t you can still lose code. If you are working as part of a team, you can either lock the files you have checked out, or you can allow anyone to edit, and all the changes will be merged when the file is updated to the repository. Either way, adding version control to your applications is sure to save you time at some point. With or without Eclipse, it is now easy to install and easy to use, so there’s really no excuse not to.

Site Tags:
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...
Posted in Software | 2 Comments »

JQuery.. my favorite plugins

August 7th, 2007

Having been developing web sites for over 8 years - I’ve learned the invaluableness of tools that help speed the production cycle. I believe in the need to know how things work, but at the same time the concept of working smarter, not harder is essential to anyone who is looking to maximize their productivity - especially when they are billing for themselves.

Along with the base jquery library, here are some of the plugins that I make use of on a more regular basis:

Dimensions by Paul Bakaus and Brandon Aaron
Dimensions is an official extension to JQuery, and allows you to easily get the positioning of any element on the page, along with its height and width. This is incredibly useful for modal dialogue boxes, error messages, etc.

Interface authored by Stefan Petre and Paul Bakaus.
Interface is the mother of all JQuery plugins, with features ranging from animation effects, to drag and drop. The whole package is 72k, but the best part is the authors allow you to grab just the parts you need for what you want to do.

Calendar authored by Marc Grabanski and extended by Keith Wood
I was in the process of writing my own JQuery based calendar when this was released. I immediately scrapped my production for their version, which makes entering dates a breeze. The many configuration options are quite nice as well.

JQuery Curvycorners - I’m trying to find the link to this, as it is no longer on the jquery plugins page. I’ll update once I do. This plugin makes rounded corners a breeze, plus it works in all major browsers AND allows borders and flows OVER background images without a problem. This plugin looks like it may be worthwhile in the meantime - as it uses canvas to draw the corners. I haven’t tried it out yet though.

Another In-Place Editor by Dave Hauenstein
I made some modifications to this to add external field validation and inline image uploading (which I’ll probably post at some point in the future). This plugin is great on its own, and very easy to extend. In case you hadn’t guessed - it allows in-place form field editing.

Highlightfade by Blair Mitchelmore
Simple method to show your users that something AJAXy has happened.

Tooltip by Joern Zaefferer
Allows highly customizable creation of tooltips to suit nearly any need.

Site Tags:
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...
Posted in Ajax, Jquery | 1 Comment »

Goodbye Windows Vista

August 7th, 2007

How ironic, that I resume updating this space on a regular basis by continuing where I left off over two months ago. If you check the post previous, you’ll see the point at which I began by cursing Windows Vista for the poor performance of Adobe Photoshop - yet in the end decided that the slowness was in fact a blessing in disguise.

Slowness I can handle. Instability, I cannot.

I was recently trying to apply a windows update, when Vista up and froze on me. Not a temporary freeze, but a ‘you must unplug your computer to get out of this freeze’ (BTW - does anyone know how to unstick a frozen machine without unplugging it? Yeah, power button is real useful when you can only use it to turn the power ON). Upon restart, the computer - having crashed in the middle of an update - could not figure out how to complete the boot back into Vista. This resulted in an episode of restoring the system to its previous point (before the update). Normally, this would not have been a big deal - however by that point I felt like a boxer who had already gone 10 rounds too many against an opponent who was lacking in intelligence, but made up for it in sheer endurance. Of all the problems I had encountered with Vista - a Windows Update causing it to crash… that was the knockout punch.

I did a system restore to the point immediately preceding the update, and proceeded to move all of my important files off to an attached network drive. Muttering sharply beneath my breath the entire time, I waited until I had completed my backups, and then gleefully restarted and booted into my Windows XP cd. I must admit, I have rarely felt as joyful as I did when I elected to format the partition, and watched the progress bar slowly erase all of those painful Vista memories.

Having re-installed XP, I was reminded of what it was like to have an efficient working environment again. Photoshop once again ran smoothly, my hard disk no longer spun for reasons I could not fathom, and all was again right with the world.

Except for one thing.

Does anyone out there want a slightly used copy of Windows Vista Ultimate?

Site Tags:
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...
Posted in Software, Vista | No Comments »