Archive for the category “Codebits”

March 10th, 2009 at 5:29 pm

JavaScript printf()

The printf function is known in many programming languages. It allows to replace a certain pattern in a string with other strings.

Here's a little printf() for JavaScript. It can't do very much; in fact, it only can replace the placeholder %s multiple times.

JAVASCRIPT:
  1. var printf = function(string)
  2. {
  3.     if (arguments.length <2) { return string; }
  4.         for (var i=1; i<arguments.length; i++)
  5.         { string = string.replace(/%s/, arguments[i]); }
  6.     return string;
  7. }

Although it's not too advanced, it can be helpful if want to produce something as a pagination:

JAVASCRIPT:
  1. var pagination = '';
  2. var numpages = 5;
  3.  
  4. for (var page=1; page<=numpages; page++)
  5. {
  6.     pagination += printf('Page %s of %s', page, numpages);
  7. }

Update 08.04.09, 12:11: Found a better solution.)

February 24th, 2009 at 8:48 pm

Implementing PHP functions in JavaScript

There are some handy functions in PHP you would sometimes like to have in JavaScript, too. Why not reimplement them? It's not hard. Take for example in_array() and explode():

JAVASCRIPT:
  1. function explode(delim, val_to_split)
  2. {
  3.     return (val_to_split.indexOf(delim))
  4.         ? val_to_split.split(delim)
  5.         : [val_to_split];
  6. }
  7.  
  8. function in_array(needle, haystack)
  9. {
  10.     hlength = haystack.length;
  11.     for (var i=0; i<length; i++)
  12.         { if (needle == haystack[i])
  13.             { return true; } }
  14.     return false;
  15. }

Hint: On many pages of PHP functions, there are comments which describe how to reimplement a function (e.g. PHP 4 implementations of PHP 5 functions) -- in PHP though, but it's easy to adapt them for JavaScript.

December 17th, 2008 at 12:32 pm

Unclutter array definitions in PHP

Here's a little trick how to print definitions of large arrays in a more beatiful way. Instead of passing a set of strings to the array() function, pass only one string to the explode() function!

For example, consider a section in the WordPress code (/wp-includes/post.php):

PHP:
  1. // currently
  2. $data = compact( array( 'post_author', 'post_date', 'post_date_gmt',
  3.     'post_content', 'post_content_filtered', 'post_title', 'post_excerpt',
  4.     'post_status', 'post_type', 'comment_status', 'ping_status',
  5.     'post_password', 'post_name', 'to_ping', 'pinged', 'post_modified',
  6.     'post_modified_gmt', 'post_parent', 'menu_order', 'guid' ) );
  7.  
  8. // equals
  9. $data = compact( explode('|', 'post_author|post_date|post_date_gmt|post_content|'.
  10.     'post_content_filtered|post_title|post_excerpt|post_status|post_type|'.
  11.     'comment_status|ping_status|post_password|post_name|to_ping|pinged|'.
  12.     'post_modified|post_modified_gmt|post_parent|menu_order|guid' ) );

Not only is the second part shorter, but it is also easier to edit and to overview. Of course this always depends on how many elements your array has; it's rather ridiculous with small arrays.

December 11th, 2008 at 10:28 am

Lightweight JSON fetcher (3rd party capable!)

JSON is a great data transfer format, especially for AJAX style applications (much better than XML for that purpose). Fetching JSON from your server is usually not a big deal these days, since all common browsers provide the XMLHttpRequest.

But: It can be a big problem to fetch data from a third party server, due to the Same Origin Policy. Imagine you want to provide a service where people simply need to include a JS file from your server to make great things happen on their own sites. Fetching JSON with your script via XMLHttpRequest (even from your own server) will not work.

However, there's a great workaround, which I first saw at Jeffrey Sambells' site. His solution is more generic, as it's able to load any JavaScript (not only JSON data) dynamically. Also, it's compatible with the XMLHttpRequest functions. I just needed something to fetch my JSON, and I don't need all of the XMLHttpRequest. Yet I do want to use AJAX indicators and error handling. So I used his code and taylored a lightweight JSON fetcher. If compressed with a JavaScript packer, it is as tiny as 1.4 kB.

The client side

Here's the code for the fetcher. Save it as request.js or something and have it loaded with your other JS. You can also insert into other JS files.

JAVASCRIPT:
  1. /*
  2.     XssJsonFetch
  3.     (C) 2008 Alex Günsche
  4.     Available under the MIT license
  5.     based on XssHttpRequest (c) 2005 Jeffrey Sambells <info@jeffreysambells.com>
  6.     see info and terms of use: http://jeffreysambells.com/posts/2006/03/06/centralized_ajax_services/
  7. */
  8.  
  9. var XhrCount = 0;
  10. var XhrWatchList = [];
  11. reqjson = [];
  12.  
  13. var Xhr = function() {
  14.     this.ins = ++XhrCount;
  15.     this.u;
  16.     this.so;
  17.     this.w;
  18.     this.wc = 0;
  19.     this.to = 5;
  20.     this.responseText = null;
  21.     this.status = null;
  22.     this.readyState = 0;
  23. };
  24.  
  25. Xhr.prototype.onerror = function() {};
  26. Xhr.prototype.onload = function() {};
  27.  
  28. Xhr.prototype.srs = function(a) {
  29.     if (this.readyState <a || a == 0) {
  30.         this.readyState = a;
  31.  
  32.         if (this.readyState == 2)
  33.         {
  34.             this.srs(3);
  35.             if(typeof reqjson[this.ins] != 'undefined')
  36.             {
  37.                 var re = reqjson[this.ins];
  38.  
  39.                 // this is more secure, but sometimes fails on complex objects
  40.                 //re = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test( re.replace(/"(\\.|[^"\\])*"/g, ''))) && re || false;
  41.  
  42.                 re = re || false;
  43.  
  44.                 this.responseText = re;
  45.                 this.status = (re) ? 'ok' : 'string error';
  46.       }
  47.             else
  48.             {
  49.                 this.status = 'noresult';
  50.                 this.onerror();
  51.             }
  52.  
  53.             this.so.parentNode.removeChild(this.so);
  54.             reqjson = [];
  55.             this.srs(4);
  56.             this.onload();
  57.         }
  58.     }
  59. };
  60.  
  61. Xhr.prototype.load = function(u)
  62. {
  63.     this.u = u;
  64.     this.so = document.createElement('script');
  65.     this.so.id = 'reqjson'+this.ins;
  66.     this.so.charset = 'utf-8';
  67.  
  68.     this.srs(1);
  69.     this.so.type = 'text/javascript';
  70.     this.so.src = this.u + (this.u.indexOf('?') != -1 ? '&': '?') + 'jsonvar=reqjson' + this.ins;
  71.     this.so = document.getElementsByTagName('head')[0].appendChild(this.so);
  72.     XhrWatchList[this.ins] = this;
  73.     this.w = setInterval('XhrWatchList[' + this.ins + '].wl()', 50);
  74. };
  75.  
  76. Xhr.prototype.wl = function()
  77. {
  78.     this.wc++;
  79.     if (typeof reqjson[this.ins] != 'undefined')
  80.     {
  81.         clearInterval(this.w);
  82.         this.srs(2);
  83.     }
  84.     else if ( this.wc>= (this.to*20) )
  85.     {
  86.         clearInterval(this.w);
  87.         this.status = 'timeout';
  88.         this.onerror();
  89.     }
  90. };

The server side

Of course, you need a part on the server to generate the dynamic parts. In this example, we simply output the date, but it can be any data that is expressible with a JSON string (and that's a lot). Save it as ajax.php in the same directory on the server.

PHP:
  1. <?php
  2.     header("Expires: Mon, 01 Jan 2000 05:00:00 GMT");
  3.     header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
  4.     header("Cache-Control: no-cache, must-revalidate");
  5.     header("Pragma: no-cache");
  6.     header("Content-Type: text/javascript");
  7.  
  8.     // $results could as well be an array or any type of a scalar
  9.     // if you use an array, be sure that the keys and structure match what your JS expects
  10.     $results = date('d.m.Y H:i:s');
  11.  
  12.     $json = json_encode($results);
  13.  
  14.     $reqvar = preg_match('|^reqjson[0-9]+$|', $_GET['jsonvar'])
  15.         ? 'reqjson['.str_replace('reqjson', '', $_GET['jsonvar']).']'
  16.         : 'reqjson[0]';
  17.  
  18.     echo "$reqvar = $json;";
  19. ?>

... and a demo

A little demo to show you the integration into your own project. Save it as demo.html in the same directory as the other two, then load it in your browser.

HTML:
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  2.     <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
  3.     <script type="text/javascript" src="request.js"></script>
  4.     <style type='text/css'>
  5.         #main { border: 1px solid #888; padding: 10px; margin: 50px auto; width: 30em; }
  6.         #dynfield { color: #090; }
  7.         #button { border: 1px outset #888; padding: 3px; background: #eee; cursor: pointer; }
  8.     </style>
  9.     <script type='text/javascript'>/* <![CDATA[ */
  10.     window.onload = function()
  11.     {
  12.         var $ = function(el) { return document.getElementById(el); };
  13.  
  14.         // the event to trigger the request
  15.         $('button').onclick = function()
  16.         {
  17.             // if you use an indicator, make it appear here
  18.  
  19.             // any URL, relative or absolute, with parameters or without, even from a third-party server
  20.             var url = "ajax.php";
  21.  
  22.             var http = new Xhr;
  23.             http.load(url);
  24.  
  25.             http.onload = function()
  26.             {
  27.                 // hide your indicator
  28.                
  29.                 // here happens everything you need to perform with your fetched JSON
  30.                 var serverdate = http.responseText;
  31.                 if (serverdate) { $('dynfield').firstChild.data = serverdate; }
  32.             };
  33.  
  34.             http.onerror = function() {
  35.                 // some error handling (and hide indicator)
  36.                 alert('Error: ' + http.status);
  37.             };
  38.         };
  39.     };
  40.     /* ]]> */</script>
  41.     <title>AJAX demo</title>
  42. </head>
  43.     <div id='main'>
  44.         <p>The server date is: <strong id="dynfield"> </strong></p>
  45.         <p><span id="button">retrieve</span></p>
  46.     </div>
  47. </body>
  48. </html>

November 19th, 2008 at 12:29 pm

Lightweight password generator

Here's a snippet of PHP code that can create passwords. It can create passwords of different lengths, it can use different sets (uppercase and lowercase letters as well as numbers), and it can be told to exclude potentially confusing characters.

PHP:
  1. <?php
  2. function passgen($length=8, $reqsets='uln', $noconfusing='true')
  3. {
  4.     $length = (int)$length;
  5.     if ($length> 20 || $length <3) $length = 8;
  6.  
  7.     // some characters look alike. let's optionally exclude them.
  8.     $confusing = ($noconfusing === 'true') ? 'O01Il' : '';
  9.  
  10.     $randchars = $token = '';
  11.  
  12.     $sets = array(
  13.         'u' => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
  14.         'l' => 'abcdefghijklmnopqrstuvwxyz',
  15.         'n' => '0123456789'
  16.         // you can even add an own set
  17.     );
  18.  
  19.     if ($reqsets)
  20.     {
  21.         $reqsets = str_split($reqsets);
  22.         foreach ( array_keys($sets) as $availset )
  23.             if ( in_array($availset, $reqsets) )
  24.                 $randchars .= $sets[$availset];
  25.     }
  26.  
  27.     if (!$randchars)
  28.         $randchars = implode($sets);
  29.  
  30.     for ($i=0; $i<=$length; $i++)
  31.     {
  32.         do
  33.         {
  34.             $lpos = mt_rand( 0, strlen($randchars)-1 );
  35.             $letter = substr($randchars, $lpos, 1);
  36.         }
  37.         while ( in_array($letter, str_split($confusing) ) );
  38.  
  39.         $token .= $letter;
  40.     }
  41.     return $token;
  42. }
  43.  
  44. echo passgen($_GET['length'], $_GET['sets'], $_GET['noconfusing']);
  45. ?>

If you intend to use this in a script, please keep in mind that mt_rand() needs to be seeded/initialized properly.

June 11th, 2008 at 11:03 am

Shell script to optimize all tables in all databases (MySQL)

If you have many databases with many write operations, it may be that the table overhead takes a good amount of space. (This is due to the fact that MySQL doesn't free the space of deleted entries.) With "optimizing" the tables, you can free that space.

Save the following script as /usr/local/sbin/optimizealltables.sh, make it chmod 700 (very important!), then replace YOURPASSWORD with your root MySQL password.

CODE:
  1. #!/bin/bash
  2.  
  3. MYSQL_LOGIN='-u root --password=YOURPASSWORD'
  4.  
  5. for db in $(echo "SHOW DATABASES;" | mysql $MYSQL_LOGIN | grep -v -e "Database" -e "information_schema")
  6. do
  7.         TABLES=$(echo "USE $db; SHOW TABLES;" | mysql $MYSQL_LOGIN |  grep -v Tables_in_)
  8.         echo "Switching to database $db"
  9.         for table in $TABLES
  10.         do
  11.                 echo -n " * Optimizing table $table ... "
  12.                 echo "USE $db; OPTIMIZE TABLE $table" | mysql $MYSQL_LOGIN >/dev/null
  13.                 echo "done."
  14.         done
  15. done

April 16th, 2008 at 11:20 am

Clear a sized select field

If you have have a select form element with a size attribute, one common option for the user is to leave it empty (especially in combination with multiple). The problem is, as soon as one or more options are selected, it is quite impossible in most browsers, to not select anything at all. And even if there is a way, it is not easy to accomplish. Try for yourself to deselect all items:

With a little JavaScript magic, we can offer a button to clear the select field:

JavaScript:
  1. function nl_clear_select(element)
  2. {
  3.     var opt_length = document.getElementById(element).options.length;
  4.     for (var i = 0; i <opt_length; i++)
  5.         document.getElementById(element).options[i].selected = false;
  6. }

Now try again to clear the select field. Hint: clicking on "Clear selection" will help a lot. ;)

Clear selection

Neat, eh?

April 10th, 2008 at 12:14 pm

Get radio button value in JavaScript

Here's how to get the currently checked value of radio button section. The parameter elementName is the name attribute of the radio input.

JavaScript:
  1. function getRadioValue(elementName)
  2. {
  3.     var element = document.getElementsByName(elementName);
  4.     var bt_count = element.length; // can't use element.length in the loop, as it would decrement
  5.  
  6.     for (var i = 0; i <bt_count; i++)
  7.         if (element[i].checked == true)
  8.             return element[i].value;
  9. }

April 3rd, 2008 at 12:06 pm

Calculate interest rates with a shell script

If you put your cash to a bank account, you will want to know how much money you get with a certain amount at a given rate within a given period. Save the following Bash script as /usr/local/bin/loancalc (or something like that), make it executable, and you will be able to calculate the return on your investments with a single one-liner.

CODE:
  1. #!/bin/bash
  2.  
  3. function calc()
  4. {
  5.     return $(echo "scale=$2; $1" | bc)
  6. }
  7.  
  8. if [ "$1" == "-h" ] || [ "$1" == "--help" ]; then
  9.     echo "$0 calculates the interest loan of a given amount with a given rate for a given duration."
  10.     echo "Usage: $0 AMOUNT RATE DURATION"
  11.     exit 0
  12. fi
  13.  
  14. if [ -z "$3" ]; then
  15.     echo "Please enter the amount, the rate and the duration (in this order)."
  16.     exit 1
  17. fi
  18.  
  19. AMOUNT=$1
  20. ZINS=$2
  21. DURATION=$3
  22.  
  23. echo "Investment: $AMOUNT bucks at a rate of $ZINS% for $DURATION years."
  24. echo "          Loan            Total"
  25.  
  26. for i in $(seq 1 $DURATION); do
  27.     INTERESTLOAN=$(echo "scale=10; ($AMOUNT/100)*$ZINS" | bc)
  28.     AMOUNT=$(echo "scale=10; $AMOUNT+$INTERESTLOAN" | bc)
  29.     printf "Year ${i} %8.2f " $INTERESTLOAN; printf " %14.2f\n" $AMOUNT;
  30. done
  31.  
  32. printf "Final amount: %1.2f bucks.\n" $AMOUNT

For example:

CODE:
  1. you@yourmachine ~ $ loancalc 3000 3.5 5
  2. Investment: 3000 bucks at a rate of 3.5% for 5 years.
  3.           Loan            Total
  4. Year 1   105.00         3105.00
  5. Year 2   108.68         3213.68
  6. Year 3   112.48         3326.15
  7. Year 4   116.42         3442.57
  8. Year 5   120.49         3563.06
  9. Final amount: 3563.06 bucks.

December 18th, 2007 at 10:07 am

Improve loading speed of webpages by compressing HTML

Here's a simple HTML "compressor" in PHP, which will reduce the size of HTML served to the client by 10 to 20 percent, depending on your indentation style and commenting. If many of your readers have lousy bandwidth, the slight overhead of this method is worth it.

PHP:
  1. <?php
  2.     function compress($content)
  3.     {
  4.         $content = preg_replace('/[\n\t\s]+/s', ' ', $content);
  5.         $content = preg_replace('/<!--.*?-->/s', '', $content);
  6.         return $content;
  7.     }
  8.  
  9.     ob_start();
  10.     require "/var/www/htdocs/somefile.php";
  11.     $content = ob_get_contents();
  12.     ob_end_clean();
  13.  
  14.     echo compress($content);
  15. ?>

By the way, if you have a rather hungry dynamic application (e.g. WordPress with certain plugins) on a rather weak server, consider using a caching solution like 1 Blog Cacher, so you don't have to regenerate the pages everytime somebody retrieves them. And, of course, consider using output gzip compression -- be it via webserver modules such as mod_gzip/mod_deflate or based on your web application.