Tag Archives: Computing

PHP: preg_match Give Names to the Matches

So Called – Subpatterns

Patterns - preg_match

In PHP 5.2.2+ you can name the sub patterns returned from preg_match with a specific syntax.

Named subpatterns now accept the syntax (?<name>) and (?’name’) as well as (?P<name>). Previous versions accepted only (?P<name>)

This is extremely helpful, when dealing with long patterns. As you may know you can simply use the “old school” way and to call the matches by their number based index:

    $haystack = '01 Jan 1970';
    $pattern = '/(\d{1,2})\ (Jan|Feb)\ (19\d\d)/';
 
    preg_match($pattern, $haystack, $matches);
 
    print_r($matches);

Although it may look difficult to maintain, now you can simply name the sub patterns of preg_match and to call them with their associative array keys. This is more clear when writing code and it’s definitely more maintainable.

    $haystack = '01 Jan 1970';
    $pattern = '/(?<day>\d{1,2})\ (?<month>Jan|Feb)\ (?<year>19\d\d)/';
 
    preg_match($pattern, $haystack, $matches);
 
    print_r($matches);
 
    // now there's $matches['day'], $matches['month'] ...

Friday Algorithms: JavaScript Merge Sort

Merge Sort

This week I’m going to cover one very popular sorting algorithm – the merge sort. It’s very intuitive and simple as it’s described in Wikipedia:

  • If the list is of length 0 or 1, then it is already sorted. Otherwise:
  • Divide the unsorted list into two sublists of about half the size.
  • Sort each sublist recursively by re-applying merge sort.
  • Merge the two sublists back into one sorted list.

Here’s the Source

(JavaScript)

var a = [34, 203, 3, 746, 200, 984, 198, 764, 9];
 
function mergeSort(arr)
{
    if (arr.length < 2)
        return arr;
 
    var middle = parseInt(arr.length / 2);
    var left   = arr.slice(0, middle);
    var right  = arr.slice(middle, arr.length);
 
    return merge(mergeSort(left), mergeSort(right));
}
 
function merge(left, right)
{
    var result = [];
 
    while (left.length && right.length) {
        if (left[0] <= right[0]) {
            result.push(left.shift());
        } else {
            result.push(right.shift());
        }
    }
 
    while (left.length)
        result.push(left.shift());
 
    while (right.length)
        result.push(right.shift());
 
    return result;
}
 
console.log(mergeSort(a));

It’s interesting to see what happens in the Firebug’s console:

[34, 203, 3, 746] [200, 984, 198, 764, 9]
 
[34, 203] [3, 746]
 
[34] [203]
 
[3] [746]
 
[200, 984] [198, 764, 9]
 
[200] [984]
 
[198] [764, 9]
 
[764] [9]
 
[3, 9, 34, 198, 200, 203, 746, 764, 984]

Actually the tricky part in this algorithm is the merge function – it does all the work.

Replace the Broken Images with a Default Image with JavaScript

There is cool JavaScript trick that helps you catch broken images. You know that when the image doesn’t exist, the http path to the image returns 404 or the path is wrong, the browser doesn’t display nothing in the most cases. As MSIE is always different it displays an ugly icon saying that there is not an image to load

MSIE broken image icon

and that is really bad!

There’s a Quick Fix …

Simply add an onerror handler on the IMG tag

<img src="http://..../broken_url.jpg" onerror="this.src='path_to_default_image'" />

Zend_View_Helper_InlineScript Appends Scripts Twice

Double Trouble

duplicate
This is a well known problem, which is well described as a bug in Zend Framework’s issue tracker. Once you add some scripts with the inlineScript helper you’ll receive them twice in the code. This makes the page slower and leads to some crashes.

$scripts->appendFile('my-file1.js')
        ->appendFile('my-file2.js')
        ->appendScript('alert("test")');

This will print the alert twice.

<script src="my-file1.js"></script>
<script src="my-file2.js"></script>
<script>
//<!--
alert("test");
//-->
</script>
<script>
//<!--
alert("test");
//-->
</script>

Quick Solution

Although this is the worst solution I’ve ever made – it works! There is a check for duplicates in the HeadScript helper around line 240:

if (!$this->_isDuplicate($content)) {
...

and then a check in the _isDuplicate method(), ~ line 270:

if (($item->source === null)
    && array_key_exists('src', $item->attributes)
    && ($file == $item->attributes['src']))
{
    return true;
}

The thing you’ve to do is to add such a check for the appendScript() and not only for appendFile() method – again ~ line 230:

case 'script':
	if (!$this->_isDuplicate($content)) {
	    $item = $this->createData($type, $attrs, $content);
	    if ('offsetSet' == $action) {
	        $this->offsetSet($index, $item);
	    } else {
	        $this->$action($item);
	    }
	}
	break;

And then slightly modify the _isDuplicate method:

foreach ($this->getContainer() as $item) {
    if (($item->source === null)
        && array_key_exists('src', $item->attributes)
        && ($file == $item->attributes['src']))
    {
        return true;
    }
    if ($item->source == $file) {
        return true;
    }
}
return false;

HTML5 geolocation – What If the User Doesn’t Share His Position?

HTML5 Geolocation

So far we were used to expect something like this from our mobile phones with built-in GPS support. Every image or video clip then was automatically “tagged” with latitude & longitude geo data. With HTML5 coming features we discover new cool things we can do with our browsers. Such cool thing is the geolocation.

Geo Location

Support

As you may guess not every browser is supporting these HTML5 features, but out in the web there is quite good collection of tables comparing different browsers and their support level.

Firefox

This – as expected is a browser that supports this geo tagging. First of all you’ve to allow your browser to use your geo coordinates, as this can be private information.

Browser GEO Location

Once you do it you can access the geo coordinates, which by the way are quite accurate, with JavaScript.

What if you don’t share your position?

What happens if you don’t want to share your position? Actually I ran in this situation and as my application waited the coordinates – it was completely blocked.

The examples doesn’t show you something special. They simply describe how to get the coordinates, but doesn’t tell you what if the user doesn’t click on the “share” button.

if (!!navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(getPos);
}
...
 
function getPos(position) 
{
    position.coords.latitude;
    position.coords.longitude;
}

Of course getPos() can be simply an anonymous function:

if (!!navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(function(position) {
            position.coords.latitude;
            position.coords.longitude;
        });
}

Only the Firefox documentation tells you how to handle errors, simply add one more parameter – callback, for getCurrentPosition() method:

if (!!navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(getPos, onError);
}
...
 
function getPos(position) 
{
    position.coords.latitude;
    position.coords.longitude;
}
 
function onError()
{
   // handle error
}

Now you know where you don’t want to be.

Map Marker