Posts

Showing posts from 2011

Css animations with Emile

Emile is a great little js animation library created by Thomas Fuchs who created script.aculo.us and scripty2 and blogs here . We've used Emile on BenefitCosmetics for homepage animations and I've also used it on my personal homepage . Presentation here Tips: - layout the page, style it with css then plan on how to animate the images etc. on the page. - if you plan to animate a css value (e.g. left) then be sure to initialize it using css first; otherwise will get errors - animating "opacity" did not work for me in IE, which does opacity differently anyway. Instead I just changed display of items from none (hidden) to block (show). - if you have multiple main separate animations on the page (as BenefitCosmetics does) then stop the current before playing the next I'd like to try the other animation library scripty2, seems pretty cool.

State Pattern for Online Checkout

Image
The essence of a good checkout experience is that its easy for the customer to complete the sale and that it successfully hides all the work happening "under the covers". Because alot more is involved in checkout than the typical user realizes. As the user progresses through checkout, tasks such as data validation, ensuring cart consistency and reserving stock and price, address verification, add/remove promo codes, gift wrap and messaging, payment authorization, fraud controls, downstream order processing and persistence are all happening in a typical checkout. Note: I do not consider add/remove to/from cart manipulations as part of checkout. Checkout starts when the user decides to checkout with whats already been added to their cart. MVC is a standard pattern for building UIs but coding all that checkout logic and functionality into a controller/model of MVC is not a good fit for a number of reasons: - decoupling the checkout business logic from model/controller allows

Online Checkout usability best practices for developers

The following are a list of developer to-dos my teammate Dice and I have gleaned. There are lots of other ux best practices, you can find some good lists of those elsewhere such as here and here for example (simple, fast and clean is common). 1. Set autocomplete off for private information such as card holder name, card number, cvc code and dates to ensure information previously entered is not displayed to the wrong people. i.e. <input autocomplete="off" id="cardNumber"/> You can set it off at form level or individual input field level. I prefer input field level since you may want other fields such address on the form to autofill. FYI this is also a godo diea to use for passwords too. Mozilla post with more. 2. Don't store card information on your server to meet PCI Complicance. Many Checkout apis allow you to send card information in a javascript api (jsonp) which returns a token for your use thereafter. A simple trick to avoid submitting ca

Modify Headers FF plugin

Very handy little plugin to Add or Modify Http headers After you install you should start Modify headers (you can also Stop is and disable individual headers) Then you can choose to Add or Modify or Filter headers. I needed to send Accept-Language as en-gb only (and turn off en-us), so I - started modify headers - selected Modify action from drop down - added header Accept-Language and value en-gb - then hit Add btn - ensure the header is enabled (green btn) Then refresh your link Looking in Firebug Net panel I now see the following passed Accept-Language en-gb Help http://www.garethhunt.com/modifyheaders/help/?v=0.7.1.1 SoapUI is another tool for such effects but this is simpler.

Reebok portable configurator

I worked on the Reebok portable configurator in 2009. An actionscript app to be embedded on sites and blogs such as this. It's fully operational so feel free to select a shoe and play with it. Alternative Content

PHP passes array by value unless you declare function signature to take reference

yep, calling the function below will not have changed the array after the call public function addMore(array $names) {    $names[] = 'another';    return; } ..you have to declare the function signature to take a reference to the array, then the array will be changed after the call public function addMore(array &$names) {    $names[] = 'another';    return; } Objects passed can be modified without the need to declare as references in the signature as they are passed by reference by default;

Accessing symfony uri values

Some useful info: $request->getHost()   uk.ben.local $request->getUri()   http://uk.ben.local/frontend_dev.php/checkout/shipping sfContext::getInstance()->getRouting()->getCurrentInternalUri(false)   checkout/shipping sfContext::getInstance()->getRouting()->getCurrentInternalUri()   checkout/shipping url_for(sfContext::getInstance()->getRouting()->getCurrentInternalUri(false))   /frontend_dev.php/checkout/shipping sfContext::getInstance()->getRouting()->getCurrentRouteName()  default

SVN Externals

You can point your repo to a trunk, branch or tag of another repo. Do this using svn externals On a pc you can right click on a repo folder, you'll see a tortoise svn tab. Click that tab, hit properties and you can add a property such as an svn:external Can define like this:   myExternal https://11.11.111.111:1111/repo/branches/mybranch OR   myExternal https://11.11.111.111:1111/repo/trunk Now the folder myExternal will point to that other repo and will have a local copy of its code (whihc you can commit to if you have permissions) You can also include a specific rev number Just svn update you local repo to pickup latest for yours and any externals

Run IE6 as vm

Run ie6 as vm instance 1. install vmplayer http://www.vmware.com/products/player/ 2. get ie6 vm tar, unpack uing 7zip (you must have an ie6 tar created from os disks and packaged using vmware) 3. then in vmplayer go to that ie6 and open its vm file 4. play the new vm and open ie6 within that os 5. hit any url now 5. for local testing urls enter ur ip name as base url (type ipconfig in command line and us IPv4 Address. e.g.    http://75.101.110.170/frontend_dev.php/brand/holiday/videos

Ruby on Rails

Well, the time has come to get stuck into Ruby on Rails v3.0. I'm excited. So I bought 2 peepcode videos (basic I and II) and am watching them. I have rails and dev kit installed locally on my pc and we're ready to start coding. First, I have to say how similar symfony is to rails. Same folder structure, same tasks such as generating an app, use of yml files for configuration etc. Plus my experience creating Rest apis in my most recent project with backbone.js will serve me well with Rails. more to come...

Using Mercurial Hg to Pull and Commit

On my latest project I need to use Mercurial Hg as source control tool. I'm on windows so I use Tortoise Hg (who also prvide svn and cvs ui tools) One big difference thus far is committing to and updating from the repo is a 2 step process for Mercurial. When getting changes from the central repo, you must Pull the changes (changeset) but then also merge and commit then to your local (just pulling is not enough). You must commit your own local changes first before you can commit the pulled changes. Tortoise hg synch menu has an option to just pull all or view a list of pulls and decide what to accept. From the docs: Pull changes from the group repository into your repository,  TortoiseHg ‣ Repository Browser  or  hgtk log , choose the path to the group repository in the syncbar and then  Pull . If some changesets were pulled, merge those changes with your local changes and then commit the merge into your local repository. From the changelog viewer ( TortoiseHg ‣ Repository

Facebook app hosting on Heroku

Check it out here

Considerations when working with China team

For Benefit Cosmetics the first site launched in March 2011 was for China site. Hardworking, helpful people. Remind me a great deal of many Americans I've met. Some major considerations: - Language and time zone challenge collaboration. Our end of day in SFO is Chinas start. Many spoke little English and none of us Chinese. So language can be a challenge. Expect to work some late late nights, I did. - In my experience, some Chinese respond better to top down direction from their boss than as self starters. So if work is not getting done then you may get more success driving it from top down (just like it works here too!!) - China addresses are different: e.g. districts, subdistricts - Facebook, youtube, twitter not allowed and google is day by day. China has own versions. - China will typically use their own Chinese payment gateways (e.g. Alipay). Plus Chinese are more used to Cash on Delivery (i.e. not pay until delivered) - Currency symbol is different, but number format

css float is your friend

Many designs I see have text extreme left and right of page. Padding etc is not the way to go. The way to accomodate this is using css floats. The important thing is to float clear after your floating (otherwise layout goes awry). If you've floated both left and right previously then you'll need to clear: both otherwise you can use clear: left/right as appropriate

jQuery dialog setButton text, no title bar

There are 2 formats to pass buttons: as an object and as an array of objects. Using the latter you can set the button text attribute. This is the approach to use for localizing the text. e.g. (minor changes to protect) Here's the Gist Hide title bar: notice the dialog class noTitleDialog? Does as it says, css in the gist.

Backbone.js binding and unbinding (no free lunch)

For devs used to other thick client RIAs like actionscript, adding and removing listeners is second nature. But for js devs using an MVC library such as Backbone it may come as an unexpected surprise and be the cause of bugs. Event driven programming is a good way to go, add listeners, fire the event, handle the event. BUT you have to remember to remove the listeners if the listener is no longer interested or is otherwise being removed from play. If you don't it can be the source of errors and/or leaks. This is supported in Backbone.js with unbind(), you call it just like you do with bind i.e. // add listner to do save if user oks save on save dialog, as well as cancel saveDialog.unbind("updateOkd", this.updateOkd ); saveDialog.unbind("updateCancelled", this.updateCancelled ); ...and here's the bind // add listner to do save if user oks save on save dialog, as well as cancel saveDialog.bind("updateOkd", this.updateOkd

Isotope: An exquisite jQuery plugin for magical layouts

Check it here Can be combined with Infinte Scroll plugin

Infinite scroll - an alternative to next and prev

Interesting plugin

Making AJAX Applications Crawlable

Overview Spec from google

Best way to pass params from php to javascript

Use json_encode, better than simple parameter replacement e.g. <script type="text/javascript"> var myObj = {}; myObj.config = <?php echo json_encode($my_config); ?>; </script> Then later in js you can call myObj.config.field1, where field1 is a array key passed from php

Laravel configuration files per environment

You can define configurations per environment 1. Set the environment in apache:  SetEnv LARAVEL_ENV local 2. I defined an override application.php in /application/config/local and dev, test and prod Then I can access as follows: $myConfigValue = Config::get('application.myConfigValue'); Then pass to view as follows return View::make('home.index')->bind("myConfigValue", $myConfigValue); Here's what the config files looks like in /application/config/local return array( // Url for local 'url' => 'http://localhost', 'myConfigValue' =>  'yesDoIt' ); Of course, see the laravel documentation for all this and more.

My Jumble of Links

Ok, until I find a better place..(browsers crash too ya know!) jQuery and js jquery this http://remysharp.com/2007/04/12/jquerys-this-demystified/ js call and apply http://odetocode.com/blogs/scott/archive/2007/07/05/function-apply-and-function-call-in-javascript.aspx js module pattern http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth Blogs http://addyosmani.com http://www.joelonsoftware.com/ http://remysharp.com/ Backbone http://stackoverflow.com/questions/5097956/correct-way-to-insert-a-view-with-backbone-js http://addyosmani.com/blog/building-spas-jquerys-best-friends/ http://joeybeninghove.com/2011/08/16/backbone-screencast-introduction-views/ http://backbonetutorials.com/ http://www.elfsternberg.com/2010/12/08/backbonejs-introducing-backbone-store/ http://peepcode.com/products/backbone-js http://dailyjs.com/2011/04/04/node-tutorial-19/ http://blog.paracode.com/2011/08/23/image-gallery-with-backbone/ http://oneofthesedaysblog.com/bac

Backbone.js models and jsonp

Checkout this gist and comments

Access Google doc as api

This is pretty cool, here's one way in a goolge doc, click Share ->Publish to Web click Start Publishing you can choose output format for spreadsheets e.g. html, csv, txt etc you'll see a url on the page, you can actually now hit that url This is where it gets cool, you can issue a curl command against that url and pipe to a file e.g. curl 'https://docs.google.com/spreadsheet/pub?hl=en_US&hl=en_US&key=<the_key>&output=csv' -o data.csv So you can curl a google doc onto a server!

Arrays as static properties in php

The syntax is a little strange (note the self::$..) below: // the space at the start of each value is required private static $httpResponseCodes = array('200' => ' 200 OK' , '400' => ' 400 Bad Request' , '401' => ' 401 Unauthorized' , '403' => ' 403 Forbidden' , '404' => ' 404 Not Found' , '408' => ' 408 Request Timeout' , '409' => ' 409 Conflict' , '500' => ' 500 Internal Server Error' , '503' => ' 503 Service Unavailable' ); public static function lookupHTTPResponse($code) { // if passed a code which does not exist then return 500 if (! isset(self::$httpResponseCodes[$code])) { $code = '500'; } return self::$httpResponseCodes[$code]; }

jQuery find all checkboxes checked

voila $('input:checkbox[checked]') You could do something like this to find all within tbody and then check the length of the resulting set ($('tbody input:checkbox[checked]').length == 0);

HTML Tables are ok in some circumstances

Image
Yes, indeed, HTML Tables are ok in some circumstances, for example: - laying out table data e.g. a list of items - laying out forms. I know you can float each label and then clear to go onto a new line. But I had a page which was using floats already to create left and right columns. Then within the right floated column I had some form controls. Frankly, the css got complicated. Everything was float: left, I used clear:left  and I had alot of css to set margins etc. I switched to using tables to layout the form data and it was a simpler solution, less "brittle" if layout had to change. Please see screenshot below for the result (still a work in progress). Remember to set table width, usually 100%. Otherwise table will resize to size of data. You can set widths of <th> columns to define the width of each column, using % or pixel. You can align text left, right as well as up and down. To do so, use text-align and vertical-align . You can use these css properties at

How to handle backbone.js model save() to PHP server

Well just as I was making nice progress saving model updates on the client, I ran into an issue: backbone.js by default for mode.save() will call HTTP PUT passing json data. Turns out php cannot handle that so well.  After checking the php superglobals to no avail, I found this post:   http://www.lornajane. net/posts/2008/Accessing- Incoming-PUT-Data-from-PHP Using this approach, I actually got the server side code to work and handle the default backbone.js model.save(). However its a bit convoluted and took some time to work it out. I think the better approach maybe to use a backbone switch as follows:  setting  Backbone. emulateJSON = true;  will cause the JSON to be serialized under a  model  parameter, and the request to be made with a application/x-www-form- urlencoded  mime type, as if from an HTML form" In that case, I can get the "model" param passed, urldecode it, json_decode it and use it as associative array. *Note: I since saw in backbone.js code comments

Supporting searches in Rest APIs

To use query parameters or not that is the question. Consider this post from StackOverflow  Notice that the first 2 answers identify two different approaches (nested url or query parameters) and support in the community is practically evenly split (22 vs 21). Google web services such as search make extensive use of query parameters. But I do note Google search is an algorithm which has to accommodate a large range of queries. Urls generally look and work (e.g. easier to remember, caching etc) better than query parameters but there is a point at which you get deeper and deeper into nested paths that it stops making sense and/OR search combinations become too complicated. At that point it makes sense to use query parameters. I refer to this book and quote:  "Query variables are perfectly acceptable for naming algorithmic resources"  The author makes the case for uris but explains there's also a place for query parameters, especially for algorithmic resources such as sea

Backbone.js, laravel, Mercurial and Amazon Web Services SimpleDB

Yeah! working with all of these technologies for a microsite, all new to me so stay tuned for progress updates. Backbone.js is more than powerful, it's a paradigm shift. An update 9/7/2011 Backbone.js - remember for each view method to include each method in the call to _.bindAll() so that this can be used - if I want to use regex in a Router it appears I have to manually add the route in initialize() e.g. this.route(/search/, "search", this.list); // matches url with /search in it and calls list() - be careful of what model/model events you bind views to; can have unintended consequences - backbone.js is a new framework, there are some examples and Q&A on stackoverflow but some questions are harder to answer. I would also like to see a little more in the documentation e.g. using regex in route - I think I created too many view classes for parts of the main list page. So I removed 2 views and just consolidated them into the main list view class. Other vie

Rapid prototyping in Fireworks

Well its an expensive toy but pretty cool I must say. I've never used Fireworks before but have used Photoshop some. I was trying to understand a wireframe flow for a new microsite and decided the best way to validate would be to create an image with screen flow on it to review with the designers. Then I thought why not a working prototype? I have a trial Adobe Fireworks so I decided to try it. Well as my kids program "yo-gabba-gabba" likes to say: I tried it and I like it. Approach: - I took screenshots of each of the Wireframes, pasted each on as a separate page into Fireworks - add hotspot links from buttons to pages. - save, File->export - go to file system and open the first page into browser, click on links, it works! Pretty dang cool! Here's the tutorial I followed More usefil info - to add a new page, click Edit->Insert->Page - to add a hotspot link, click the toolbar hotspot link, then draw a box around the button, then on the bottom p

bash scripting

A favorite resource: Another  for ifs More scripting Here's a snippet of a simple script I wrote recently for checking logs, outputting errors or counting frequency. can be used like:    ./cl.sh accepts count    ./cl.sh accepts Uses fgrp for faster searching. Some content changed for privacy reasons. Can also be piped to file using >output We plan to put on a chron and could perhaps add in some email alerts #!/bin/sh #if passed no param then grep for exception (no case sensitivity, then exit) if [ $# -eq 0 ] then    fgrep -i "Exception" mylog.log    exit 1 fi echo "$1 passed as argument, so using that" echo "$2 2nd argument" # search for that login exceptions # if test $1 == 'login' then   search_str='....' # seach for all rejects # elif test $1 == 'rejects' then   search_str="..." # seach for all accepts # elif test $1 == 'accepts' then   search_str="....&quo

Linux Top for monitoring

Linux command top is a great powerful tool to see server load and even manipulate processes.   Type top on command line to start. Type q to quite The load average top right show 3 numbers: current load, recent load and past load. The number is a measure of load where >3 is not so good and 5 is bad Also shows tasks running, sleeping etc Shows CPU Shows Swap Shows processes running. For example as Apache receives requests you can see more Apache processes being spawned and then disappearing. For each process you can see the CPU and memory it's using. Keep an eye out for Java/Tomcat processes as they often consume alot. More here

Debugging in IE including Firebug like element highlighting and real time css editiing

There are ways especially with IE8 (which you can also run in IE7 compatible mode) Javascript debugger You can step through javascript and have IE break on failing js line. On IE8 hit F12 and the debugger opens. - click Script tab to get to the html - click Start Debugging button on toolbar - to the right of Start Debugging button is a dropdown to select script - click left column of js code to add a breakpoint (red ball). You should see breakpoints listed on the right. Works well, I've used this to debug and find a number of issues. Html element and css editor IE8 offers a pretty good html element highlighted and editor too. On IE8 hit F12 and the debugger opens. - click HTML tab to get to the html - expand the html to get to your html - clicking on an html node should highlight it on the browser page (useful to find where things are positioned) - on right side is css applied which you can edit - you can edit the html and add css styles real time, tab off to

New Benefit US site launched today

We launched Benefits new US website today The US release is built on the same common codebase and paltform as Benfits  China site launched last  March. As Tech Lead for both launches I've been lucky to work with some great developers and teamates.  We developed the US site in approx 2.5 months, then tested and tuned for approx 1 more month. For US I worked on designing and coding including: integration with the new Payment Gateway for PCI compliant credit card processing changes and consolidation for US and rest of world addresses for single and multi shipments Cybersource integration for address validation adding Ajax interactivity to checkout pages so pages show impact to cost as changes are made We split my work into 6 sprints over a 2.5 month period and except for the Payment Gateway integration most everything was on time. The Payment Gateway integration as expected had some surprises. Other members of the team worked in parallel on UI changes. A great team effor

Symfony redirect throws an sfStopException so don't wrap the redirect in a try catch

This is a strange one but when in an action and you call the symfony redirect, $this->redirect(module/action), symfony will redirect and also throw an sfStopException exception! Here's a link with more We had the redirect call within a try catch and thus the symfony exception was caught (which is not what we wanted). The fix was to move the redirect call outside the try catch, another option in the post is to call $this->getController()->redirect()

Run IE8 as IE7 and use IETester for IE6

Useful http://techie-buzz.com/browsers/ie7-browsing-mode-in-ie8.html I also use IETester (free desktop app) to test for IE6. Its not perfect but pretty close.

loader timer using jQuery dialog

We have a gift and needed a loader display I created a loader js module using jQuery dialog and it's coded to display when ajax calls start and then hide when ajax calls stop. Could make model by setting the dialog modal param to true. var loadingTimer = (function() { var $timer = $('#loadingHopup'), init = function(){ _dialog(); _listeners(); }, show = function() { $timer.dialog("open"); }, hide = function() { $timer.dialog("close"); }, _dialog = function() { $timer.dialog({ create: function (event, ui) { $(".ui-widget-header").hide(); }, open: function() { // allow safari/chrome users to use scrollbar window.setTimeout(function() { $(document).unbind('mousedown.dialog-overlay').unbind('mouseup.dialog-overlay'); }, 100); }, close: function() { }, dialogClass: 'noTitleDialog', height: 200, width: 200, position: '

SVN Merge using Tortoise svn OR command line

Before you start you should find the revision number in the source folder you want to merge forward from. Steps: ensure all is committed and its updated in target folder go to target folder (you want to merge into) and right click and choose Merge on screen 1, I usually choose "Merge range of revisions"  and click Next. But if you want to merge from a Branch then select the Merge from Branch 2nd option and then on next screen choose the Branch URL to merge from.  on screen 2 "Merge Revision Range", choose url to merge from (i.e. source) on screen 2, enter revision range to merge e.g. 1230-Head.   This means merge revision 1230s to Head from the source to the target you selected in step 2 i.e. a range. You could also just merge a single revision number or more than one delimited by commas. You can click Show Log button to see a list of revision to choose from. click Next on screen 3 "Merge Options", you can click Test Merge to see what a merge wou

jQuery to get all input fields which are not hidden nor display: none

jQuery is sooo powerful, no wonder its used on almost half the worlds sites. Here's some code to find in #myForm all input types of text which are not hidden fields or display: none and iterate over them         $('#myForm input[type=text]:input:not(input:hidden)').each(function() {             console.log("In each and value is: " + $(this).val() + " id is: " + this.id);                                 }); There is a difference between input[type=hidden] and input:hidden. The latter includes type hidden as well as display none which is what I wanted.

jQuery and jsonp

I recently has recourse to build a jQuery jsonp integration. A workaround to the browsers same origin policy. I discovered this little black art that is not well documented at all.  There's a few useful links on the web but not alot to go on, even on jQuery site. Here's my code with some explanation below:      // I setup an object literal to set the data, then stringify it (name your fields as you need)      //      var callData = {                    Field1: "Denis",                    Field2: "0",                    Field3: "Test"             };      var JSONRequestData = JSON.stringify(callData);      $.ajax({                   dataType: 'jsonp',                 jsonpCallback: 'postProcessingCallBack',                 url: 'http://myserver.com/myjsonphandler?jsoncallback=?',                 data: JSONRequestData,                 async: false                    });    You must set dataType to jsonp.