Javascript, PHP, and sorting

Does your daily development have you jumping between client and server code like mine often does?

I recently needed to sort an array of “documents” from a NoSQL DB in PHP. So off to PHP.net to review the docs… there are 13 array sort functions in the table of choices. I decided on usort because my JSON was an array of objects – which is represented in PHP by an array of associative arrays – where I want to sort on a field of the child array. Note the description for usort explains it sorts by value using a user defined function, in my case the value is each child array and I want to sort on the Object-ID field.

Here is the JSON:

photos: [
   {
      Object-ID: 1,
      Location: "http://foo/x.jpeg"
   }, {
      Object-ID: 2,
      Location: "http://foo/y.png"
   }
]

The Javascript idiom for this would be:

photos.sort(function (p1, p2) {
   return p1['Object-ID'] - p2['Object-ID']
});

Please note I know the Object-ID field is an int but you should consider datatypes in your scenario.

The point of this story is my initial PHP solution just didn’t feel right. First of all you write your 1 line sort function and then supply a string of the name as the 2nd argument to usort. While not a big deal having a string match a function name and hoping over the lifetime of the code they never get out of sync nags at me.

The next irritant was my code was in a class so this syntax did not work (as an aside a static method does not work either) and as the docs point out (in example #3) you can pass an array with the class name AND the sort function name. Darn now we have two magic strings.

   usort($photos, array('MyClass', 'sortby_object-id'));

Then I ran into this great “Functional Programming in PHP” reference:
http://www.phptherightway.com/pages/Functional-Programming.html

Nice!

   usort($photos, function ($p1, $p2) {
      return $p1['Object-ID'] - $p2['Object-ID'];
   });

I will admit if you read far enough down on the PHP doc page you will see example #4 using a closure which might also get you to this syntax but never the less PHP: The Right Way is worth a look.

Sencha Touch lists and the disclosure Icon

Sencha Touch provides a few ways to do lists, the one I most often turn to is the “simple” list.  This component has an itemTpl config where you create your markup and when you attach a store to it the template gets repeated for each item producing the HTML.

For example this code:

sencha list code 1

Produces this view:

sencha list 1

Note that the framework implements the clickable disclosure icon (added automatically because of the onItemDisclosure config) as a DIV with a CSS3 :before pseudo element for the visuals.

The problem in this layout though is that it’s absolutely positioned at the top right of each list item. For this design it is supposed to be next to the address (outlined in red for debugging).

One solution is to remove it by settting the onItemDisclosure property to false and then manually add a DIV into the address block and use the existing Sencha CSS class on it like:
<div class="x-list-disclosure"></div>
But wait that didn’t work! It looks the same, what’s the deal?

At first I thought maybe I made a mistake removing the original because the disclosure arrow was in the exact same position but no it’s the new one I just manually added. After reading the 4th reference link below it becomes clear, the absolutely positioned disclosure icon moves up to the 1st relatively positioned element. In this case the list item.

As the blog post by Chris Coyier points out this may be a CSS “Ah-ha!” moment for you… “relative positioning gives you the control to absolutely position children elements inside of it”.

OK so the solution is then easy — set the address DIV to position: relative, i.e.

.x-list-item .a-openhouse-address {
    position: relative;
}

That’s it! Now the icon stays inside the address div and because we used the Sencha class it still responds to touch events as designed.

sencha-disclosure-correct

References:

  1. http://docs.sencha.com/touch/#!/guide/list
  2. http://docs.sencha.com/touch/#!/api/Ext.dataview.List
  3. http://docs.sencha.com/touch/#!/api/Ext.dataview.component.SimpleListItem
  4. http://css-tricks.com/absolute-positioning-inside-relative-positioning/