Monthly Archives: October 2008

Fixing Dead Centre approach with jQuery

I was worked on a centred project design of a website. When I met such requirement I’ve always used Dead Centre approach.

Unfortunately I’ve noticed that when the content is larger than the screen the top-left corner is not visible. In that current project the logo of the site was exactly on that place, so it’s really confusing.

I had to solve this issue in order to satisfy the clients requirements. So, I’ve used jQuery to sort this out.

You can see the difference in these 2 examples:

Resize your browser window in order to see the difference.
How it’s working?

First of all there are 2 javascript includes:

<script type="text/javascript" src="jquery-1.2.6.min.js"></script>
<script type="text/javascript" src="jquery.dimensions.min.js"></script>

After this there is a function which track the size of the screen and the content.

<script type="text/javascript">
        /*Track height and width of the window and the content*/
        function resize(){
            if($(window).height() < $('#content').height()){
                $('#horizon').css('top', '0px');
                $('#content').css('top', '0px');
            } else {
                $('#horizon').css('top', '50%');
                $('#content').css('top', '-'+($('#content').height()/2)+'px');
            }
            if($(window).width() < $('#content').width()){
                $('#content').css('left', ($('#content').width()/2)+'px');
            } else {
                $('#content').css('left', '50%');
            }
        }
       
        //Bind events on resize
        $(document).ready(function(){
            resize();
        })
        $(window).bind("resize", function(){
            resize();
        });
    </script>

The explanation of the code:
I am using jQuery plugin named jQuery Dimensions Plugin 1.1 which extract the proper dimensions of the boxes.
The function checking if the content screen is bigger than the window size, if so it change the CSS in order to fit properly. I guess that you can see the logic easily. So, no more explanations here.

Hope this will help someone.

Adding autocomplete field for search in WordPress

Added a nice Autocomplete field of the search box in that blog /top right/. It’s really nice to have and I really enjoyed doing it.

I followed that article: How to: Create an Ajax-based Auto-completing Search Field for your WordPress Theme, but instead of using suggested js code, I’ve used Script.aculo.us Autocomplete way.

I really enjoyed and I hope you will like it too.

Update: I’ve wrote a plugin for this: nik.chankov.net/autocompleter/. Enjoy!

Working with nested data and find method with breadcrumbs in CakePHP

Do you working with tree data in your projects?

Well, in CakePHP there is a Tree behavior which will help you to handle such structures. Let me show you how to use it in your projects. Hierarchical data structures are very well described here by Mike Hillyer and I would suggest you to take a look before you continue reading.

Let’s say we have following data structure:

CREATE TABLE IF NOT EXISTS `categories` (
  `id` INT(10) NOT NULL AUTO_INCREMENT,
  `parent_id` INT(10) DEFAULT NULL,
  `name` VARCHAR(255) DEFAULT NULL,
  `lft` INT(10) DEFAULT NULL,
  `rght` INT(10) DEFAULT NULL,
  PRIMARY KEY  (`id`)
)

Note, that in that table there are 3 special fields: parent_id, lft and rght.

The first one is very familiar to everyone who understanding the tree structures. The other 2 are to handle the MPTT logic (see the article mentioned above). The beautiful part of using Tree behavior is that you don’t need to worry about these 2 extra columns. The behavior will fill them automatically. πŸ™‚

So, continue with the example. Attach the Tree behavior to your Model:

<?php
class Category extends AppModel {
    var $name = 'Category';
    var $useTable = 'categories';
    var $actsAs = array('Tree' => 'nested');
}
?>

That’s it. Now when you save (insert or update) your data into the table, the fields lft and rght will be automatically populated with the correct values. Of course your task is to have proper value set in parent_id πŸ™‚

Why this is so important?
As you already know /if you read the article for MPTT/ using lft and rght values will give possibility to get very easy nested data in various ways.
In Model::find function there is already threaded option, but what about having breadcrumbs?

Here is a way to extend the Model::find function with this functionality. /inspired by Daniel Hofstetter’s post/

<?php
class Category extends AppModel {
    var $name = 'Category';
    var $useTable = 'categories';
    var $actsAs = array('Tree' => 'nested');

    public function find($type, $options = array()) {
        switch ($type) {
            case 'breadcrumbs':
                if(!isset($options['fields']))
                    $options['fields'] = null;
                if(!isset($options['recursive']))
                    $options['recursive'] = null;
                if(is_object($this->Behaviors->Tree) && $options['id']){
                    return $this->Behaviors->Tree->getpath($this, $options['id'], $options['fields'], $options['recursive']);
                } else {
                    return null;
                }
                break;
            default:
                return parent::find($type, $options);
        }
    }
}
?>

As you can see I am using the function TreeBehavior::getpath. There are a lot of handy functions in this behavior, but for breadcrumbs example this is just enough.

How to use it?

$this->Category->find('breadcrumbs', array('id'=>1));

so if you have data like this:

1 Root
2     Cat1
3         Cat1.1
4     Cat2

and use the function mentioned above with id=3 the result will be:

Array
(
    [0] => Array
        (
            [Category] => Array
                (
                    [id] => 1
                    [parent_id] =>
                    [name] => Root
                    [lft] => 1
                    [rght] => 8
                )
        )

    [1] => Array
        (
            [Category] => Array
                (
                    [id] => 2
                    [parent_id] => 1
                    [name] => Cat1
                    [lft] => 2
                    [rght] => 5
                )
        )

    [2] => Array
        (
            [Category] => Array
                (
                    [id] => 3
                    [parent_id] => 2
                    [name] => Cat1.1
                    [lft] => 3
                    [rght] => 4
                )
         )
)

After this with

$breadcrumbs = Set::extract('/Category/name', $result);
echo ' / '.implode(' / ', $breadcrumbs);

you will have the following result

/ Root / Cat1 / Cat1.1

I am leaving to you the styling of it as well as adding the links to the parent nodes.

Building cake application (Part VI)

Saturday (Day 6)

Problem with validation messages while translating
Although my native language is Bulgarian and the requirement from the client was to have this site only in Bulgarian, I’ve preferred to have it in English and to make the translation with the i18n functions of CakePHP. There are 2 reasons to do this:

1. This will give me the possibility to show you the result of all these days of coding and
2. I can reuse some part of the codes the same as I’ve used in this project

So, up to my experience having application in English is never a bad idea. πŸ™‚

You know, that the translating process is not very exciting process, but someone need to do it and because there is no one who can help me with this I’ve start the translation. Anyway. πŸ™

While translating I noticed that the most of the validation messages are not appear of the translation file. I knew this from my past experience, but I needed to find an easy and elegant solution to translate these messages instead of putting them in all views. Putting in the view you need to do this at least 2 times.
Continue reading

Building cake application (Part V)

Friday (day 5)

Constructing SQL statement for the search
Yep, today I need to finish the Profile search for the admin part. As I mentioned, the search is only by fields of experience, so there is no big and scary where clause /especially if you want to cover all cases, like splitting the words with AND, OR etc. will cause huge where with all possible combinations/.

There are 2 specific requirements here: The results need to be ordered by relevance and the report need to show fields of competence which are match to the search criteria next to each row /user/.

What does it means? Let’s say there are 2 users. First one has following skills like Java, PHP, MySQL, HTML and JavaScript, the second one knew only JavaScript and HTML, so when we search for users matching criterion PHP and HTML, the search results need to be ordered like this:

User1 – matching fields: PHP, HTML – relevance 2 criteria matched
User2 – matching fields: HTML – relevance: 1 criteria matched
and so on.

At first glance it look like I had to build huge SQL including few sub queries or functions for fetching the fields of relevance and matching fields and I was prepared for at least one day to accomplish this task, but in fact it was very fast.
Continue reading

Building cake application (Part IV)

Thursday (day 4)

Today I need to go downtown again. I am quite unhappy, because this mean that I need to work extra later on, but there are priorities, as you probably know. Here is what I’ve done today.

Working on the administration part
Today, I’ve worked on the administration part. There are some small bugs and glitches which I needed to clear in the Key look-up tables such as, stripping down the Categories functionality – this application requires only 2 levels of nesting in the Fields of experience, so allowing the extra levels will confuse the customers.

fixing some bugs in the front end as well
I’ve still have troubles with the redirects in the Auth component. I know it’s all my fault but it’s really annoying. I need to check what exactly is the problem with this. πŸ™

Adding delete all related records to the external user’s profile
Back to the admin part. I needed to implement delete all related records interface – if an admin user decide to remove an External user profile – let’s say someone try to test the application, or just an appropriate user /spammer/ this action should delete all relative records to that profile.

The problem was that I thought that key node is ‘dependent’ while the right one is ‘exclusive’. So, it’s set to true in the hasMany, hasOne etc. and if the parent record is deleted all records in the child tables are deleted too.
Continue reading

Building cake application (Part III)

Wednesday (day 3)

Adding dynamic pages
Today, I’ve decided to add some extra functionality to the application by adding a dynamic pages functionality. The main reason why I did this was because this system needed an “About the application” page as well as other pages and I’d preferred to leave this task to the clients. I also think that with small effort I am giving good impression to the client.

Instead of replacing fully the pages controller, I’ve decided to leave them due to use them for some system pages such as, “Thank for registration” and some other simple pages which are required.

Simple horizontal menu
Added a very light horizontal menu. I like it because it’s really small and works perfect for 1-2 level menus.

Using textile for formatting
I’ve decided to use textile for the formatting of the dynamic page’s content. There is a solution with behavior class, but I found a helper solution, so the installation and configuration was quite easy. I’ve also find a nice help description which briefly explains how to use textile format which I placed above of the page content field.
Continue reading