Archive

Author Archive

How to export customers from orders between certain dates in Magento

August 23rd, 2010

Last week a client who runs his store on Magento Commerce asked me how he could export a list of customers who purchased between certain dates in August. Of course, I first went to the Administration area and tried several approaches (order reports, customer reports, data export). Unfortunately nothing worked, so I had to write a script or a plain SQL and run it from the CLI. I preferred a straight query, rather than a script, and I tried not to use sub-selects. Here’s the adapted part, where I’ve added some variables to keep all the attribute id’s:

SET @etID := (SELECT entity_type_id FROM eav_entity_type WHERE entity_type_code = 'order_address');
SET @atFn := (SELECT attribute_id FROM eav_attribute WHERE attribute_code = 'firstname' AND entity_type_id = @etID);
SET @atLn := (SELECT attribute_id FROM eav_attribute WHERE attribute_code = 'lastname' AND entity_type_id = @etID);
SET @atEmail := (SELECT attribute_id FROM eav_attribute WHERE attribute_code = 'customer_email');

SET @startDate := '2010-08-06 00:00:00';
SET @endDate := '2010-08-13 23:59:59';

SELECT o.increment_id, e.value as email, ln.value as lastname, fn.value as firstname
FROM sales_order o
INNER JOIN sales_order_varchar e ON e.entity_id = o.entity_id AND attribute_id = @atEmail
INNER JOIN sales_order_entity lne ON lne.parent_id = o.entity_id AND lne.entity_type_id = @etID
INNER JOIN sales_order_entity_varchar ln ON ln.entity_id = lne.entity_id AND ln.attribute_id = @atLn
INNER JOIN sales_order_entity_varchar fn ON fn.entity_id = lne.entity_id AND fn.attribute_id = @atFn
WHERE o.created_at BETWEEN @startDate AND @endDate
GROUP BY o.increment_id
ORDER BY o.increment_id DESC;

The only problem is when the Shipping Name is different than the Billing Name – there’s no control over that, as we’re grouping by increment_id. This could easily be fixed in a PHP script, but the approach there should be different (using collections).

Hope this helps anyone, as it did the trick for me.

Solution tested under Magento 1.4.0.1

Magento, MySQL ,

Fixing “Catalog Price Rules” cart issue in Magento 1.4.1.0

June 29th, 2010

After recently upgrading one of my stores running Magento Commerce I found out the the latest version (at this time 1.4.1.0) had a major bug. Don’t want to sound too harsh, but unfortunately Magento’s support was again awful – there have been one thread on the forum and one issue in their bug tracking system for a while now (almost two weeks if not more) and still no update, although as I said the bug has quite an impact – even tweet’ed the problem to @magento and haven’t gotten any reply (again it’s not the first time). Yes, the product is free, yes it’s open source, but I think a bit of transparency and better communication could come to their advantage.

Bug details/behavior

So, updated from 1.4.0.1 to 1.4.1.0, everything looks fine, catalog price rules are being applied in the catalog (categories and product pages), but when adding the product to the cart the quote item price was the regular price not the special one.

Solution/Fix

After a few hours playing with the rules, observer and other core elements I found the problem. A big “thank you” goes to “myself” who posted the second comment for the issue mentioned above. The problem was within the CatalogRule Observer, when fetching the ID of the Customer Group. Here’s how to fix it:

1 – create the following folders in your Magento distro: app/code/local/Mage/CatalogRule/Model
2 – copy app/code/core/Mage/CatalogRule/Model/Observer.php to app/code/local/Mage/CatalogRule/Model
3 – open the new/copied file and go to line 105. Change this code:

        if ($observer->hasCustomerGroupId()) {
            $gId = $observer->getEvent()->getCustomerGroupId();
        } elseif ($product->hasCustomerGroupId()) {
            $gId = $product->hasCustomerGroupId();
        } else {
            $gId = Mage::getSingleton('customer/session')->getCustomerGroupId();
        }

to:

        if ($observer->hasCustomerGroupId()) {
            $gId = $observer->getEvent()->getCustomerGroupId();
        } elseif ($product->hasCustomerGroupId()) {
            $gId = $product->getCustomerGroupId();
        } else {
            $gId = Mage::getSingleton('customer/session')->getCustomerGroupId();
        }

To be more precise, you have to change hasCustomerGroupId to getCustomerGroupId on line 105.

You can now enjoy your store again!

Magento

Adding Customer Comments on Invoice PDFs in Magento (using OneStepCheckout)

January 18th, 2010

I’ve recently installed OneStepCheckout (http://www.onestepcheckout.com/) on a couple of Magento installations. The extension is very nice, really simple to integrate and I expect to see better conversion rates on the checkout process.

One cool thing is that it comes with the option of activating Customer Order Comments – it adds a textarea field on the checkout page, and a box with the customer comments in the admin, when viewing the order.

However, one of my clients requested I added these comments in the invoice PDF’s. So, here’s how to do it:

Step 1
Copy app/code/core/Mage/Sales/Model/Order/Pdf/Invoice.php to app/code/local/Mage/Sales/Model/Order/Pdf/Invoice.php

Step 2
Open the new file and create a new method:

	function insertOscComments(&$page, $order) {
		if( !$order->getOnestepcheckoutCustomercomment() ) { return; }
		$this->y -= 20;
		$page->setFillColor(new Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
		$page->setLineColor(new Zend_Pdf_Color_GrayScale(0.5));
		$page->setLineWidth(0.5);
		$page->drawRectangle(25, $this->y, 570, $this->y - 20);
		$page->setFillColor(new Zend_Pdf_Color_Rgb(1, 1, 1));
		$page->drawRectangle(25, $this->y - 20, 570, $this->y - 40);
		
		$page->setFillColor(new Zend_Pdf_Color_RGB(0.1, 0.1, 0.1));
		$page->drawText(Mage::helper('onestepcheckout')->__('Customer Comments'), 35, $this->y - 13, 'UTF-8');
		$page->drawText($order->getOnestepcheckoutCustomercomment(), 33, $this->y - 33, 'UTF-8');
		$this->y -= 50;
	}

Step 3
At the end of method getPdf add a call to the new method you created:

  /* Add totals */
  $this->insertTotals($page, $invoice);

  /* Add OneStepCheckout Customer Comments */
  $this->insertOscComments($page, $order);
}

And that’s all you need.

Magento , ,

Fixing PNG CSS backgrounds on IE6

December 17th, 2009

ie6-png-problems
Today I was stuck (again) on a really annoying IE6 glitch. In the photo, screenshot #1 is the correct display in IE6 after the fix (and all other “sane” browsers before the fix), while screenshot #2 shows the glitch. Basically, IE6 decided to replicate the beginning of the same image on all items.

You might think the problem was in my HTML code, or maybe in my CSS code. The HTML is 100% valid and following all modern guidelines: only a’s, li’s, div’s and text nodes. So, the problem could be in the CSS file – which applied a single sprite sheet on all the li’s, div’s and a’s, through background-position. In case you’re wondering what css sprites are, have a quick look: http://www.google.com/search?q=css+sprites&hl=en

So, after adding zoom, z-index, removing position: relative;, removing overriding classes, changing all background declarations to background-image, background-repeat, background-position declarations, the problem persisted. In other words, none of the regular methods worked.

After a quick-search on the internet, I found some articles discussing PNG overlaps and transparency on IE6, but also mentioning background-position‘s (http://www.dillerdesign.com/experiment/DD_belatedPNG/, http://www.hotscripts.com/forums/css/45733-solved-css-newb-overlap-issue-ie6-2-links-issue.html). Just then I realized that the problem might be with the file format – stupid, in my opinion, but not in IE6’s opinion.

Changing the file from a regular 8-bit PNG to a GIF solved the entire overlapping problem. No CSS intervention (other than changing the reference to a .gif file), no HTML edits, just an image format change.

 

Conclusion

If you don’t need images with an alpha channel and want to use background-position‘s with those images, and want to make it work with IE6, stick to GIF files. If you don’t care about IE6, then this will definitely not be not a problem for you.

 

CSS , , ,

Reducing the number of CSS requests

September 11th, 2009

One common problem with larger/trafficked websites is that they end up serving a considerable amount of css data. Most of the frontend developers use individual style sheets for resets, structure, design, homepage / innerpages and so on. In fact, there’s no other rule here than keeping the css code as maintainable as possible. This also means adding comments and maybe writing every declaration on a single line, using indents.

Another well-known problem is with caching. When the CSS file is changed, most of the times you’ll need to clear the browser cache in order to display the site correctly, with the new changes applied. Well, for users that’s not an option and all the css upgrades should be reflected instantly. I know what you’re saying: there’s Apache’s mod_expire for that, but there are times when you cannot use that or don’t know about it or you don’t know how to get it running. If you fall into this category, this article should solve that.

Let’s take an example first. On the homepage of a site, there are 3 style sheet files requests. Their total size is 46,274 bytes – that’s roughly 46KB. My aim is to only request a single CSS file and make it change its name when anything in those 3 files changes. The site uses templates, so this tutorial will be based on that architecture – for plain ole’ php-html sites, this should be even simpler.

So let’s write a list of what needs to be done:

  1. Reflect any css change into the file name so browser’s cache is instantly invalidated
  2. Combine all requested files into a single file
  3. Create a queue of css files: both templates and controller files should be able to read & write to the queue.


Step 1 – Changes to the Template Model

In the template model, add new public methods for addCss( $cssFile, $media = 'screen') and getCompiledCss($media = 'screen'). Here’s how it could look like:

function addCssFile( $file, $media = 'screen' ) { 
	$this->cssFiles[] = array( 'url' => $file, 'media' => $media ); 
	return $this; 
}

function getCompiledCss( $media = 'screen' ) {
	if( $this->compiledCss instanceof CompiledCss ) { return $this->compiledCss->getFilename(); }
	if( !count($this->cssFiles) ) { return null; }

	$cssMedia = array();
	foreach( $this->cssFiles as $css ) {
		if( !isset($cssMedia[ $css['media'] ]) ) {
			$cssMedia[ $css['media'] ] = array();
		}
		$cssMedia[ $css['media'] ][] = $css['url']; 
	}
	if( !$media || !isset($cssMedia[$media]) || !count($cssMedia[$media]) ) { return null; }
	
	$this->compiledCss = new CompiledCss( $cssMedia[$media] );
	return $this->compiledCss->getFilename();
}

Maybe the getCompiledCss seems complicated, but in fact it’s not. It’s just a proxy method with some lazy-initialization in it. It only checks to see if the CompiledCss object is instantiated (creates it if it’s not), then return the compiled CSS file name. So basically, everything is done in the CompiledCss class.


Step 2 – Changes to the template

All valid and W3C-compliant CSS declarations go in the header of the HTML, so it should be easy to group all CSS requests together and call the getCompiledCss somewhere in the main layout file or in a head template component. Either way, here’s a quick peek at how the templates could look like:

<?php 
	$this->addCssFile('general.css', 'screen')
		->addCssFile('homepage.css', 'screen')
		->addCssFile('panels.css', 'screen');
?>
<?php if( $this->getCompiledCss('screen') ): ?>
	<link type="text/css" rel="stylesheet" href="<?php echo $this->getCompiledCss('screen'); ?>" media="Screen" />
<?php endif; ?>


Step 3 – CompiledCss Class – main logic

As we’ve seen above, 99% of the logic is done inside this class, so tasks #1 & #2 are its responsibilities. First of all, remember that inside the Template Model there was only a call for getFilename() – let’s take a look at it:

function getFilename() {
	if( null === $this->filename ) {
		$this->compile();
	}
	return $this->filename;
}

Again, it’s pretty simple – all it does is to call the compile() method once. Otherwise, if this method is called more than once, it just returns the same file name. As you can see, complie() does the entire job, actually, so on with it:

First, make sure each css file gets compiled only once, then sort their names alphabetically, so that the generated file name is always the same, no matter the order you add the files (I know this can cause some serious issues – but bear with me until the end for problems, solutions & improvements

$this->cssFiles = array_unique($this->cssFiles);
asort($this->cssFiles);

The file name will need to parts: one for recognizing the css files that are “inside” and another one for content checksum – the second part helps generating new file names when the source files are modified.

$filename = $out = '';
foreach( $this->cssFiles as $css ) {
	$filename .= Crc32($css); 
	$cssPath = 'path/to/css/files/' . $css; #whatever path you need to get to the css files
	if( is_file($cssPath) && is_readable($cssPath) ) {
		$out .= file_get_contents($cssPath);
	}
}
$filename = Crc32($filename);
$checksum = Crc32($out);

We need to cache this compiled css, to be able to serve CSS data. As opposed to the method of requesting a list of css files on a GET request, this one needs to save the parsed css someplace, otherwise decoding the checksums would be almost impossible. So, write the “processed” css data to a file and than load it each time it is requested published here. Here’s the code for actually compressing the css:

$output = preg_replace('#[ \t]+#', ' ', $output); #replace multi-spaces or multi-tabs with a single space
$output = preg_replace('#[\n\r]+#', '', $output); #remove new lines
$output = preg_replace('#([:;])\s+#', '$1', $output); #remove spaces after : and ;
$output = preg_replace('#/\*(.*?)\*/#', '', $output); #remove all comments
return $output;


Step 4 – Final touches

One more step is required for this to work. You need a php file handling the compiled css request. Let’s assume your requests (and compiled file name) look like this: crc32-crc32.css. That means you’re gonna create a mod_rewrite rule in a .htaccess file mapping 8 chars, dash, 8 chars, dot css to a php file, passing both checksums as parameters. Inside the php file, just send some headers and request the file:

header('Content-Type: text/css');
header('Cache-Control: cache');
header('Pragma: cache');
header('Expires: ' . gmdate('r', strtotime('+1 year')));
echo CompiledCss::request( $firstChecksum, $secondChecksum );  

request() logic is quite simple – check for existing cache and display it, otherwise just return null. Usually, if the process runs normally, first we’re gonna get the getFilename() call which saves the cache and returns a valid file name, and just after that the request() method fires.


Compression performance

Like I said in the beginning of this post, the original file size for all three requests for this example was roughly 46K. After compilation it got to 42K – that’s around 91% of the original size, aprox. 10% compression.
Best compression level with this tools was 13%, but the usual rate is 10%. Keep in mind, however, that it depends on how the css file is written. For example, I write each declaration inline, so there are only a few spaces and new lines, but for indented css the compression could reach 20% (tested).

So there you have it. At least 10% improvement, a few extra requests saved, and the ability to invalidate browser cache on-demand. I’ve been using this tool for a while now and I can tell you I have no design/layout problems or conflicts and the total size of css requests have saved enough bandwidth – not to mention that download times are reduced. Add mod_deflate or manual gzip compression to it and it’s gonna download even faster.


Problems, Solutions & Improvements

I know some of you might have seen only problems in this article. Or you might thing this is way too complicated and it’s not needed cause there are other ways (much more simpler and faster) of doing it. So let’s see what problems I’ve identified so far and what you can do:

Problem: if CSS files are sorted and they are not compiled in the same order as they’re given, there might be conflicts, overlapping styles, and in the end the design might be screwed up.
» Solution(s): One of them is to improve your css declarations making them work the same, no matter how they’re parsed. The other solution is to remove the sorting in the compile() method, but be sure to always use the same queue push to get the same filename. For example, pushing a.css, b.css in one place an b.css, a.css in another place will create two separate css cache files.

Problem: crc32 only uses 32 bits, so checksum collisions might occur (although the chances are minimal)
» Solution: Switch to md5 or even sha1 if you think those don’t create collisions.

Problem: when stripping spaces after :;, there are chances to affect strings, like for instance url’s.
» Solution: try to keep your filenames free of : and ;, or, if this isn’t enough, remove this line: $output = preg_replace('#([:;])\s+#', '$1', $output);
The same applies for removing multi-spaces and multi-tabs.

Problem: removing comments might break some IE hacks
» Solution: hacks are not recommended anyway, so try using separate IE6- and IE7+ stylesheets, if nothing else works. Again, removing that line from the output parsing helps, but eventually the compression level would be zero.

Improvement: gzip the css and server gzip content if the client accepts gzip. Try enabling mod_deflate anyway, if load is not really an issue.

Improvement: check you inodes cache settings to help speeding disk reads – as you’ve noticed we’re reading all css files each time a page is requested, so some system tunin might help.

PHP , ,

Showing all reviews and ratings on a page in Magento

August 6th, 2009

Finally, a new post, and at last it is about Mangeto Commerce (http://www.magentocommerce.com/). In my first Magento how-to you’ll learn how to retrieve all product reviews and show them on a single page, together with the average rating. For this, I assume you have already created a new module and are able to view the page. You’ll only need to manipulate a block and a template.

First, let’s retrieve the reviews collection (this method will go into the block):

	function getReviews() {
		$reviews = Mage::getModel('review/review')->getResourceCollection();
		$reviews->addStoreFilter( Mage::app()->getStore()->getId() )
						->addStatusFilter( Mage_Review_Model_Review::STATUS_APPROVED )
						->setDateOrder()
						->addRateVotes()
						->load();        
		
		return $reviews;
	}

We’re using Mage_Review_Model_Mysql4_Review_Collection, which is a resource model. First setup the collection, filtering by store – we only want to retrieve the product reviews in the current store -, by status – show only approved reviews -, and ordering by date in reverse order, then load the collection.

addRateVotes() helps loading all the ratings/votes for that review. We’re gonna use this collection to compute the average rating.

Next, let’s move on to the template for a second. We’re gonna call the getReviews() method, then iterate through all the reviews. For each review you would probably want to display the title, nickname, date and details, but also the product associated and the user rating. For the first four, things are pretty easy, all you have to do is call getTitle(), getNickname(), getDetail(), getCreatedAt() on each review object.

To display the product name & link, we need to retrieve the product associated with each review – unfortunately I wasn’t able to find a way to join the product tables inside the query for retrieving all the reviews. So, we need to create a helper method inside our block, called getProduct(). We’re gonna use a storage/registry variable called _loadedProducts, so that we avoid loading the same product multiple times.

	function getProduct( Mage_Review_Model_Review $review ) {
		if( !isset($this->_loadedProducts[ $review->getEntityPkValue() ]) ) {
			$this->_loadedProducts[$review->getEntityPkValue()] = Mage::getModel('catalog/product')->load( $review->getEntityPkValue() );
		}
		
		return $this->_loadedProducts[ $review->getEntityPkValue() ];
	}

And inside the template:

<?php $_prod = $this->getProduct( $review ); ?>
<a href="<?php echo $_prod->getProductUrl(); ?>"><?php echo $_prod->getName(); ?></a>

One last thing, if you intend to display the average rating of each review, add another helper method inside the block:

	function getAverageRating( Mage_Review_Model_Review $review ) {
		$avg = 0;
		if( count($review->getRatingVotes()) ) {
			$ratings = array();
			foreach( $review->getRatingVotes() as $rating ) {
				$ratings[] = $rating->getPercent();
			}
			$avg = array_sum($ratings)/count($ratings);
		}
		
		return $avg;
	}

And then call it in the template (in this example we’re using Magento’s default styling):

<div class="rating-box">
	<div class="rating" style="width: <?php echo ceil($this->getAverageRating( $review )); ?>%;"></div>
</div>

That is all! You now have a page where all product reviews can be display.
Things to consider: pagination and cache!

Update: Seems that Magento comes prepared for reviews on products, categories and customers. We only need to load product reviews, so it would be wise to filter by entity. Unfortunately, the current version of Magento doesn’t allow filtering for a certain entity, only by entity and entity PK (which is the product ID in this case). Of course, we could write a decorator and write a method to just add a filter for entity_code = 'product', but the quickest (and dirtiest) way of doing it is by adding a check inside the template foreach loop (or adding a helper method in the block):


if( $review->getEntityId() == 1 ) { continue; }
//1 is the id of the 'product' entity - if you write a method, use a class constant

Note: This has only been tested on Magento 1.3.x – 1.5.x.

Magento ,

The eternal question: jQuery or MooTools?

June 23rd, 2009

It’s been a while since my last post and even more since I first thought of writing a comparison post between MooTools, Prototype & jQuery. At that time (almost a year ago), I was a huge MooTools fan. Anyone who asked me “Hey I’m starting a new project, what javascript library should I use?” got the following answer: “MooTools, of course”. Nowadays, things have changed a bit and so has my vision on js frameworks.

Although my first intention was to compare Prototype, jQuery & MooTools, I’m going to only mention the last two in this post. Not that Prototype wouldn’t be a good choice, but because I have much more experience with the other two – and also because I’m not a big “fan” of Prototype. Anyway, besides these libraries, there are at least a dozen other full javascript frameworks that you could use, so in case this is your first time you hear of such things (hmm, I doubt it though), you should check out a few of them – Ext JS, YUI, dojo, MochiKit are some of the ones I checked, heard or used.

Back to our js “battle” – I believe I’m not the only one who had to decide which one to use. So, what did I choose? Both! Not in the same project, of course, but some of my projects use jQuery, some others are based on Moo Technology. You’ll probably say this is confusing and not helping you decide which one to use. First of all, I suggest you read this great article on jQuery vs MooTools – it was a great inspirational source for me and it also contains most of the language differences and basic approach. Then, let’s try and emphasis some of the key parts of using either of these two – I’m not going into code elements, you can check the manuals for that.

jQuery

– very simple to use, so if you’re a designer or don’t have enough experience in programming (or OOP), stick to jQuery

– only one method to access dom elements – $() or jQuery() – this is great because it removes a lot of extra code, so instead of writing something like $$(selectors).each(function(el) {el.do()}) (mootools style) you can just write $(selectors).do()

– cool effects are very simple to use and can be applied really quick

MooTools

– programatic approach, so if you’re a developer or an ex-programmer (and like OOP), this is for you

– two main methods for accessing dom elements – $() and $$() – again, the code is much more simple to understand when using $$(‘#id a.class’).each(), instead of the same $(‘#id a.class’) method as jQuery does. That’s why jQuery is simple, MooTools is “correct”

– the effects part of the library is very complex and allows a lot of chaining, grouping and transition effects. again, the only problem is that it takes a bit longer to write moo-code, than j-code.

Final Thoughts

I believe it’s clear enough what the main difference between jQuery and MooTools is: it’s HOW you write javascript code. No one can really tell jQuery is best, or MooTools rules – both of them are great libraries and both of them can come in handy if you know when to use them. From my own experience, I’d say if you have a small project, more design than development, use jQuery. If you have a more complex project, that involves more javascript code, maybe reusable elements, design patterns, classes, etc – use MooTools.

I remember that I didn’t like jQuery when I first got in touch with Moo, because it was very slow. I believe it sill is slower than Moo, but the difference is not that significant on small projects.

I think it’s best to know at least one js framework and stick to that, if it makes you more productive. But I also believe it’s only to your advantage to understand how others work.

 

Pseudo-disclaimer

Aaron Newton of Clientcide, the author of “jQuery vs MooTools”, added a disclaimer in his post, so I think it wouldn’t hurt to add one myself, otherwise I might get assaulted by un-happy prototype, extjs, dojo or yui developers 🙂 I’m currently using both MooTools and jQuery, and sometimes writing a few lines of code on Prototype. I don’t intend to promote either of these frameworks, it’s really up to you which one to choose. You could even write your own!

I’d be really glad to hear some of your thoughts on javascript libraries – which ones are you using and why, why you think a is better than b, etc.

 

Resources

http://www.jqueryvsmootools.com/
http://mootools.net/
http://jquery.com/
http://www.prototypejs.org/

Javascript , ,

Custom animation using jCarousel and jQuery

May 12th, 2009

Yet another javascript demo, this time using jQuery. For those of you who haven’t worked or heard of jQuery here’s a quick explanation taken from their website: jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development.. So, first thing you need to do is go to jquery.com and download the latest version if the library.

Next thing that you need is the jCarousel plugin, written by Jan Sorgalla – visit http://sorgalla.com/projects/jcarousel/ for more details.

Dont want to read everything? You can view the online demo or jCarousel Animation (2195 downloads)

Now you’re able to add carousel effects to both vertical lists and horizontal lists. I guess 90% of the time, jCarousel is flexible enough and will let you customize a lot of things from styles to behavior. However, today I wanted to add an effect to a list and I couldn’t make the plugin work as needed. Maybe I missed something, but anyway, here’s an example on how to change the default animations for jCarousel.

First, here’s the effect I wanted: on a horizontal carousel, elements auto scroll to the right until they reach the end, then change scroll to the left until they reach the start element. Let’s call this a variant of the circular wrap that can be defined with jCarousel.

Let’s setup the carousel – include style sheets and javascripts:

<link type="text/css" rel="stylesheet" href="res/jcarousel/jquery.jcarousel.css" media="screen" />
<link type="text/css" rel="stylesheet" href="res/jcarousel/skins/ie7/skin.css" media="screen" />

<script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="res/jcarousel/jquery.jcarousel.pack.js"></script>
<script type="text/javascript" src="js/pcarousel.js"></script>

then create the carousel markup:

<div class="pCarouselWrapper">
<div class="controls">
	<a href="#" class="pCarouselPrev">&laquo; prev</a>
	<a href="#" class="pCarouselStop">stop animation</a>
	<a href="#" class="pCarouselStart">start animation</a>
	<a href="#" class="pCarouselNext">next &raquo;</a>
</div>
<ul id="pCarousel" class="jcarousel-skin-ie7">
  <li>item data 1</li>
  <li>item data 2</li>
  <li>item data 3</li>
...
  <li>item data n</li>
</ul>
</div>

I’ve added my own controls for prev() and next(), as well as a way to stop & start the animation. Now let’s configure the carousel:

jQuery(document).ready(function() {
  jQuery('#pCarousel').jcarousel({
    wrap: 'left',
    scroll: 1,
    visible: 3,
    initCallback: pCarousel.init,
    easing: 'linear',
    animation: pCarousel.animationSpeed,
    buttonPrevHTML: null,
    buttonNextHTML: null
  });
});

Some quick comments, on the outcomes – shows 3 elements at once, scrolls only one each time, the movement effect is using linear easing (check out jQuery manual for more info on this) and default jCarousel control buttons are disabled. Everything is initialized via the pCarousel.init callback.

The effect is done by the pCarousel object:

var pCarousel = {
	animationId: null,
	animationDir: 'right',
	
	//time in miliseconds to wait before scrolling
	animationTimeout: 3000,
	
	//time in miliseconds for the scrolling transition
	animationSpeed: 250,
		
	init: function(carousel) {
		// Disable autoscrolling if the user clicks the prev or next button.
		carousel.clip.hover(function() { pCarousel.halt() }, function() { pCarousel.animate(carousel); });
		pCarousel.animate(carousel);
		
		jQuery('a.pCarouselNext').bind('click', function() {
			pCarousel.halt();
		        carousel.next();
			return false;
    		});
		
		jQuery('a.pCarouselPrev').bind('click', function() {
			pCarousel.halt();
			carousel.prev();
			return false;
		});
		
		jQuery('a.pCarouselStop').bind('click', function() {
			pCarousel.halt();
			return false;
		});
		
		jQuery('a.pCarouselStart').bind('click', function() {
			if( pCarousel.animationId ) { //already running
				pCarousel.halt();
				carousel.scroll(1);
				pCarousel.animationDir = 'right';
			}

			pCarousel.animate(carousel);
			return false;
		});
	},
	
	animate: function(carousel) {
		pCarousel.animationId = setInterval( function() {
			if( carousel.last == carousel.options.size ) { pCarousel.animationDir = 'left'; }
			else if( carousel.first == 1 ) { pCarousel.animationDir = 'right'; }
	
			if( pCarousel.animationDir == 'right' ) { carousel.next(); }
			else { carousel.prev(); }
		}, pCarousel.animationTimeout );
	},
	
	halt: function() {
		if( pCarousel.animationId ) {
			clearInterval(pCarousel.animationId);
		}
	}
	
};

Again, a few explanations – there are three methods, animate(), halt() and init(). Inside init(), we’re adding listeners on DOM elements and also a pseudo-listener (via the carousel object) that freezes animation while hovering the mouse over a list item.

The halt() method simply stops the current animation, by clearing the interval. Once again setInterval comes to the rescue!

The entire animation is handled by a setInterval() call, running the animation algorithm at specific intervals – the time that you want to keep the information on the screen (in this case, it’s 3 seconds). Then, the trick is to set a scrolling direction and change it each time the carousel reaches an end. By looking at the direction, you can either call next() or prev().

Nothing fancy, nothing new, but I think it’s a nice and useful animation.

Demo | jCarousel Animation (2195 downloads)

Javascript , ,

Are you made for freelancing?

April 29th, 2009

It’s been almost two years since I’ve made the leap from the employee field to become a full time freelancer. This wasn’t something planned, it just happened, and i have to say it was (and still is) pretty exciting and challenging. Of course, there are ups and downs, there are moments when I work a few hours a day (very rare for the past 6-8 months) and there are days when I end up working 10-12 hours – best example is this blog, started almost two months ago, wrote first post more than a month ago and since then, I had no time to write another article.

For the last two years most of my friends kept telling me how cool it has to be a freelancer and decide when to work and what to work on, and how nice it was not to have a boss. On the other hand, others were trying to persuade me to get employed again, not to become isolated and too stressed by not having a steady salary. Well, as you probably know by now, there are pros and cons for each way of working, you just have to decide which ones you prefer, which ones suit you better. For example, I know people who are totally satisfied with their current job and don’t even think of starting a freelance career or working on their own company. At the same time, I’ve met a lot of people that don’t want to get back as employees and enjoy a happy freelance life – in both cases, the reasons vary from person to person.

So, the question is “Are you made for freelancing?” – should you even consider this change? I’ve tried compiling a few lists of benefits, possible problems and minimal set of must have’s “skills” (although skills is not the best word). Hopefully, these might help you decide if it’s better to keep your current job or start on a new path.

Benefits for being a freelancer/independent contractor/consultant

  • You set your own working hours
  • You choose the work you do
  • You can work from anywhere
  • You have unlimited earning potential
  • You can take time off at any point
  • You can spend more time with your family and friends or dedicate time to other projects

The challenges while being self-employed

  • Not getting paid or facing financial problems
  • Having difficulty finding work
  • Having too much work at the same time or saying “No” to potential clients
  • Feeling isolated
  • Facing problems and finding solution on your own
  • Much more responsibilities
  • Spending a lot of the working time to promote yourself or your work
  • Spending a lot of the working time get organized and optimize processes
  • Facing burnout

Benefits for being an employee

  • Stability & security – steady paychecks, well defined working hours and vacation days
  • Limited responsibility
  • Enjoying time with colleagues, team buildings
  • “Motivational packages” – phone/car/laptop
  • Paid trainings

Remember, these are just some aspects and most of them could easily go from being an advantage to being a problem – I think nothing is ever white or black, things are usually in shades of gray, so there are risks associated with all benefits. However, there are tons of resources to read and stay updated, a lot of web sites and services that can help freelancers find new projects and clients, optimize and simplify their day to day work, make new friends, socialize and expand their network, and much more. So don’t worry, you’re not really on your own. In fact, there are millions of freelancers all over the world, working as designers, developers, writers, marketeers, bloggers, translators, composers…

However, I’d like to point out that you must have some of the following skills (if not all of them), otherwise being self employed or having your own company is really not for you.

Must-have’s

  • Drive
  • Passion for what you do
  • Don’t mind the hard work
  • Self disciplined
  • Practicality and pragmatism
  • Great communication skills and networking abilities
  • Thirst for knowledge
  • Time management skills
  • Support from family and friends
  • Courage and boldness
  • Patience

I think anyone can easily add another 10 items to each list, but I guess these gave you a rough idea of how things go. Like I said, there a lot of articles on this subject, but I really recommend reading Alyssa Gregory’s articles on sitepoint.com and FreelanceSwitch.com for great articles on freelancing. You might also be interested in some <a href="http://rockablepress click here to find out more.com/minibooks/freelance-statistics-report/” onclick=”_gaq.push([‘_trackEvent’, ‘outbound-article’, ‘http://rockablepress.com/minibooks/freelance-statistics-report/’, ‘freelance statistics’]);” >freelance statistics.

I’m really interested in finding your opinions on this subject, so please leave a comment – we can all benefit from others experience.

General

Create a gallery with fade-in effects using Mootools

March 21st, 2009

I was working on a photo gallery a couple of days ago and I thought I’d write a tutorial on adding neat effects on a gallery of items (usually photos).

Demo | Mootools Gallery (907 downloads)

The problem

I was showing 12 photos on a page and I didn’t like how it loaded – it simply looked too static. So I though of adding a nice fade in effect to each item. This could be even more useful when loading the photos via an AJAX request, which I intend to add to that gallery at a later time. First, let’s take a look at the gallery HTML:

<ul class="gallery">
	<li class="clear">
		<a href="#"><img alt="img_01" src="img/01.jpg"/></a>
		<h2>Image #1</h2>
	</li>
	<li>
		<a href="#"><img alt="img_02" src="img/02.jpg"/></a>
		<h2>Image #2</h2>
	</li>

	...

	<li>
		<a href="#"><img alt="img_12" src="img/12.jpg"/></a>
		<h2>Image #12</h2>
	</li>
</ul>

I’m gonna add some basic CSS on this list, just to make it look like a grid, rather than a list – of course you can apply any styling on it.

.gallery {width: 540px; margin: 0 auto;}
.gallery li {opacity: 0; filter: alpha(opacity = 0); float: left; width: 100px; padding: 5px 10px 15px;}
.gallery li.clear {clear: left;}
.gallery li img {border: 1px solid #ccc; width: 100px;}

You can’t tell from the missing li elements, but I’m clearing each 4th element to create a 4×3 grid. Ok – so far the grid is in place, but we need the animation part – we could use any javascrpit framework, but for this project I had to use Mootools – for those of you that haven’t seen it and don’t what it is about, here’s a quick overview from their site: MooTools is a compact, modular, Object-Oriented JavaScript framework designed for the intermediate to advanced JavaScript developer.

The solution

First, we need to fetch all li elements:

var li = $$('ul.gallery li');

then apply the animation effect:

li.each(function(e) {
e.set('tween', {duration: 500, transition: 'back:in'}).tween('opacity', 0, 1);
});

A few comments on this last piece of code:

  • e.sets(…) – set the duration to 500 and transition to “backIn” to all tweens
  • e.tween(‘opacity’, 0, 1) – animate (or tween) opacity from 0 to 1, using the options defined above

If you run this code you can clearly see that it doesn’t exactly produce the desired effect – all photos fade-in at once, because of the way the code is executed. The trick is to add an incremented timeout to each element:

var i = 0; //the current timeout
li.each(function(e) {
  i += 100; //adding the increment
  setTimeout( function() {
    e.set('tween', {duration: 500, transition: 'back:in'}).tween('opacity', 0, 1);
  }, i);
});

And that’s all! We now have a nice item-by-item fade-in effect. It’s worth mentioning that this effect can be changed by tweaking the three variables: the delay for each item, the speed of the effect and the tween effect. On the demo page I’ve made it possible to change the delay & speed, so you can make an idea of how they affect the general effect. The third parameter can be changed using any mootools transition (http://mootools.net/docs/Fx/Fx.Transitions).

Demo | Mootools Gallery (907 downloads)

Javascript , ,