function is_valid_email_syntax(email)
{
    email = email.toLowerCase();
    email = email.replace(/^\s+|\s+$/g,"");
    
    match = email.match(/^[a-z0-9._%+-]+@[a-z0-9._-]+\.[a-z]{2,4}$/);
    return (match != null);
}

function is_valid_url_syntax(url)
{
    var regexp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/

    url = url.toLowerCase();
    url = url.replace(/^\s+|\s+$/g,"");
    
    return regexp.test(url);
}

//
// Translate.
//
function translate(str, val)
{
    var lc_str = str.toLowerCase();
    
    if (lc_str in g_lang)
    {
        var translation = g_lang[lc_str];
        
        if (val)
        {
            translation = translation.replace('%s', val);
        }
        
        return translation;
    }
    
    else
    {
        return str;
    }
}

//
// Clear field
//
// Clears field contents, unless its current
// value is different from default value.
//
function clear_field(field_id, default_val)
{
    if (field_id.value == default_val)
    {
        field_id.value = '';
    }
}

//
// Does the opposite of clear-field().
//
function reset_field(field_id, default_val)
{
    var val = field_id.value;
    val = val.replace( /^\s+/g, "" );
    
    if (val == '')
    {
        field_id.value = default_val;
    }
}

//
// Is input an array.
//
function is_array(input)
{
    return typeof(input)=='object' && (input instanceof Array);
}

//
// Cookies.
//
// http://www.quirksmode.org/js/cookies.html
//
function _create_cookie(name, value, minutes, is_ssl) 
{
    if (minutes) 
    {
        var date = new Date();
        var milisec = minutes * 60 * 1000;
        date.setTime(date.getTime() + milisec);
        var expires = "; expires="+date.toGMTString();
    }
    else 
    {
        var expires = "";
    }
    
    var cookie_def = is_ssl ?
        name+"="+value+expires+"; secure" :
        name+"="+value+expires+"; path=/";

    document.cookie = cookie_def;
}

function create_cookie(name, value, period_str) 
{
    var minutes;
    
    var isSecure = false;
    
    var matches = period_str.match(/([0-9,-]+)\s([a-z]+)/);
    
    if (matches == null)
    {
        my_alert('Invalid input period: '+period_str);
        return false;
    }
    
    var amount = parseInt(matches[1]);
    var type = matches[2];
    
    if (type == 'minutes')
    {
        minutes = amount;   
    }   
    
    else if (type == 'days')
    {
        minutes = amount * 24 * 60;   
    }   
    
    else if (type == 'years')
    {
        minutes = amount * 365 * 24 * 60;   
    }   
    
    _create_cookie(name, value, minutes, isSecure) 
}

function create_secured_cookie(name, value, days) 
{
    var isSecure = true;
    var minutes = days * 24 * 60;
    _create_cookie(name, value, minutes, isSecure) 
}

function read_cookie(name) 
{
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');

    for(var i=0;i < ca.length;i++) 
    {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(nameEQ) == 0) 
            return c.substring(nameEQ.length,c.length);
    }
    
    return null;
}

function erase_cookie(name) 
{
    _create_cookie(name,'',-1, false);
}

function erase_secured_cookie(name) 
{
    create_secured_cookie(name,"",-1);
}

//
// Strip whitespace from the beginning 
// and end of a string
// 
function trim(str)
{
    return str.replace(/^\s+|\s+$/g,'');
}

// 
// Make sure that textBox contains 
// a numeric value.
// 
function force_numeric_value(textBox)
{
    var val;
    
    if (textBox.value == '-')
    {
        return;
    }

    while (textBox.value.length > 0 && isNaN(textBox.value))
    {
        textBox.value = textBox.value.substring(0, textBox.value.length - 1);
    }

    textBox.value = trim(textBox.value);
}

// 
// Realtime hour-field validation.
// 
// NOTE: also automatically appends a 
// dash between hour and minute.
// 
function validate_hour(textBox)
{
    var val = textBox.value;
    var length = val.length;
    
    //
    // case blank string - return.
    //
    if (val.length == 0)
    {
        return;
    }
    
    //    
    // Error - first digit is not 0-2.
    //
    if (!val.match(/^[0,1,2]/))
    {
        textBox.value = '';
        return;
    }                
    
    //    
    // Error - second character is not a digit.
    //
    if (!val.match(/^\d\d.*/))
    {
        textBox.value = val.substring(0,1);
        return;
    }                
    
    //    
    // Error - hours number is above 23.
    //
    if ((length >= 2) && (parseInt(val.substr(0,2)) > 23) )
    {
        textBox.value = val.substr(0,1);
        return;
    }                
    
    //    
    // Case dd: - return
    //
    if (val.match(/^\d\d:$/))
    {
        return;
    }                

    //    
    // Error - not ddd
    //
    if ((length == 3) && (!val.match(/\d\d\d/)))
    {
        textBox.value = val.substr(0,2);
        return;
    }                

    //    
    // Append ':'
    //
    if ((length == 3) && (val.substr(2,1) != ":") )
    {
        textBox.value = val.substr(0,2) + ':' + val.substr(2,1);
        
        val = textBox.value;
        length = val.length;
    }          
    
    //    
    // Error - minutes first digit is not in
    // the range 0-5.
    //
    if ((length > 3) &&(parseInt(val.substr(3,1)) > 5))
    {
        textBox.value = val.substr(0,2);
        return;
    }                

    //    
    // Error - not dd:dd
    //
    if ((length == 5) && (!val.match(/\d\d:\d\d/)))
    {
        textBox.value = val.substr(0,4);
        return;
    }                

    return;      
}

// 
// Realtime numeric value validation.
// 
function validate_number(textBox)
{
    var val = textBox.value;
    var length = val.length;
    
    if (!val.match(/^[\d\.]*$/))
    {
        textBox.value = val.substr(0,length-1);
    }                

    return;
}

//
// Is input string a JSON.
//
function is_json(in_str)
{
    if (typeof(in_str) != 'string')
    {
        return false;
    }
    
    var type = typeof(jQuery.parseJSON(in_str));
    
    return (type == 'object' || type == 'string'); // assi - I added the 'string', it may be wrong.

    /*var filtered = in_str;
    filtered = filtered.replace(/\\["\\\/]/g, '@');
    filtered = filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
    filtered = filtered.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
    
    return (/^[\],:{}\s]*$/.test(filtered));*/
}

//
// Converts json string into a json object.
//
function eval_json(json_str)
{
    if (json_str == '')
    {
        alert('Error: Blank input at eval_json()');
        return '';
    }
    
    return eval("(" + json_str + ")"); // assi
    
    if ( ! is_json(json_str))
    {
        return false;
    }
    
    else
    {
        return eval("(" + json_str + ")");
    }
}

//
// Is input json string contains an error 
// messaage.
//
function is_json_error(json_str)
{
    var json = eval_json(json_str);
    return (json.error !== undefined);
}

//
// Parses error message from input json sting.
//
function get_json_error(json_str)
{
    var json = eval("(" + json_str + ")");
    var error_msg = json.error;
    
    if (error_msg == undefined)
    {
        alert ('Input is not json error at get_json_error()');
    }
    
    error_msg = decode_from_json(error_msg);
    
    return error_msg;
}   

//
// Table hover.
//
function table_hover()
{
    $("table.regular tr:odd").addClass("odd");
    $("table.regular tr:even").addClass("even");
    
    $("table.regular tr").hover
    (
        function()
        {
             $(this).addClass("hover");
        },

        function()
        {
            $(this).removeClass("hover");
        }
    );
}

//
// Is input string combined of input
// character group only.
//
function _is_valid_chars(in_str, validChars)
{
    var isNumeric = true;
    var chr;

    for (i = 0; i < in_str.length && isNumeric == true; i++) 
    { 
        chr = in_str.charAt(i); 
        
        if (validChars.indexOf(chr) == -1) 
        {
            isNumeric = false;
        }
    }

    return isNumeric;
}

function is_numeric(in_str)
{
    var validChars = "0123456789.-";
    return _is_valid_chars(in_str, validChars);
}

function is_image(file)
{
    file = file.toLowerCase();
    return file.match(/.[jpg|png|jpeg|gif]$/) != null;
}


//
// Delay.
//
function delay(millSec)
{
    var date = new Date();
    var curDate = null;

    do 
    { 
        curDate = new Date(); 
    }
    
    while (curDate-date < millSec);
} 

//
// Displays success messages.
//
function ok_msg(id, msg)
{
    $("#"+id).html(msg);
    $("#"+id).removeClass("error");
    $("#"+id).addClass("success");
    $("#"+id).show();
}

//
// Displays error messages.
//
function error_msg(id, msg)
{
    $("#"+id).html(msg);
    $("#"+id).removeClass("success");
    $("#"+id).addClass("error");
    $("#"+id).show();
}

//
// Displays a message.
//
function my_alert(msg, box_id)
{
    if (box_id != null && box_id != '')
    {
        $("#"+box_id).text(translate(msg)).effect("highlight",{},1500);
    }
    
    else
    {
        alert(translate(msg));
    }
}

//
// Returns token value, parsed from current URL.
//
function get_get_variable(var_name)
{
    //
    // Parse query variables from URL.
    //
    var url = window.location.href;
    var url_ary = url.split("?");

    if (url_ary.length == 0)
    {
        return "";
    }

    var query = url_ary[1];
    
    if (query == undefined)
    {
        return "";
    }
    
    var vars = query.split("&");

    //
    // Reset output.
    //
    var output = "";

    //
    // Set output value (if exists in URL) 
    //
    for (i=0; i<vars.length; i++)
    {
        var keyval = vars[i].split("=");

        if (keyval[0] == var_name)
        {
          output = keyval[1];
          break;
        }
    }
    
    //
    // Convert escape code.
    //
    output = unescape(output);

    //
    // Convert "+"s to spaces.
    //
    output.replace(/\+/g," ");

    //
    // Return output.
    //
    return output;
}
    
//
// Returns token value, parsed from current URL.
//
function get_current_token()
{
    var token = get_get_variable('token');
    token = token.replace(/#.*/, '');
    
    return token;
}

//
// Builds URLs.
//
function get_url_screen(screen)
{
    var token = get_current_token();
    var url = INDEX_URL+'?'+screen+'&token='+token;
    
    return url;
}

function get_url_action(action)
{
    var token = get_current_token();
    var url = INDEX_URL+'?action='+action+'&token='+token;
    
    return url;
}

//
// Returns current URL target.
//
function get_current_url_target()
{
    var match = location.href.match("#(.*)");
    return is_array(match) ? match[1] : '';
}

//
// Set tab.
//
function set_tab(id)
{
    id = 'tab_'+id;
    
    $('#tabs .tab').removeClass('activetab');
    $('#'+id).addClass('activetab');
}

//
// Interface to jQuery ajax.
//
// INPUT:
//
// . POST data in the form of 'a=1&b=2...'
//
// . ID of HTML box, where error messages should
//   be injected.
//
// . Code to be run (through 'eval'), in case of 
//   a successful server response. Response is
//   inserted into the code before evaluation,
//   by replacing the string '%%%'.
//
// . Optional input: show and hide div ID values.
//   It is used for hiding the clicked button,
//   and displaying a 'contacting server' 
//   indication.
//
function ajax(data, code, msg_box_id, hide_id, show_id, is_https)
{
    data += '&token='+get_current_token();

    if (is_https)
    {
        var url = 'https://isether.com/login/login.php';
    }
    
    else
    {
        var url = INDEX_URL;
    }
    
    if (hide_id)
    {
        $('#'+hide_id).hide();
        $('#'+show_id).show();
    }
    
    $.ajax
    ({
        type: "POST",
        url: url,
        data: data,

        success: function(response)
        {                       
            if (hide_id)
            {
                $('#'+hide_id).show();
                $('#'+show_id).hide();
            } 
            
            /*if (response === 'null')
            {
                msg = "Null server response";
                my_alert(msg, msg_box_id);
                return false;
            }*/
            
            /*if ( ! is_json(response))
            {
                msg = "not json: "+response;
                my_alert(msg, msg_box_id);

                return false;
            }
            
            else */
            
            if (response == '')
            {         
                //my_alert('Blank ajax response', msg_box_id);
                return false;
            }
            
            else if (is_json_error(response))
            {         
                msg = get_json_error(response);
                my_alert(msg, msg_box_id);
                return false;
            }
            
            else
            {
                var decoded_response = eval_json(response); 
                var str = code.replace(/%%%/g, 'decoded_response');
                eval(str);
            }
        },

        error: function (XMLHttpRequest, textStatus, errorThrown) 
        {
            if (hide_id)
            {
                $('#'+hide_id).show();
                $('#'+show_id).hide();
            }
            
            msg = 'ajax error: '+textStatus+' : '+errorThrown;
            my_alert(msg, msg_box_id);
            return false;
        }
    });
}

//
// Display screen through ajax.
//
function display_ajax_screen(action, input)
{
    var data = 'action='+action;
    
    if (input != '')
    {
        data += '&' + input;
    }
    
    ajax(data, "$('.tab_contain .content').html(%%%)", "screen_message");
}

//
// Parses extention out of input file name.
//
function parse_file_ext(file_name) 
{
    return file_name.substring(file_name.lastIndexOf('.') + 1,file_name.length).toLowerCase();
}

//
// Removes extention from file name.
//
function remove_file_ext(file_name) 
{
    return file_name.replace('.'+parse_file_ext(file_name), '')
}

//
// Strips HTML tags from string.
//
function strip_tags(str)
{
    str = str.replace(/\<\/?.+?\>/gi, "");
    str = str.replace(/\[\/url\]/gi, "");
    
    return str;
}

/**
 * jQuery-Plugin "clearField"
 * 
 * @version: 1.0, 31.07.2009
 * 
 * @author: Stijn Van Minnebruggen
 *          stijn@donotfold.be
 *          http://www.donotfold.be
 * 
 * @example: $('selector').clearField();
 * @example: $('selector').clearField({ blurClass: 'myBlurredClass', activeClass: 'myActiveClass' });
 * 
 */

(function($) {

jQuery.fn.clear_field = function(settings) {
    
    settings = jQuery.extend(
    {
        blurClass: 'clear-field-blurred',
        activeClass: 'clear-field-active'
    }, settings);
    
    jQuery(this).each(function() {
        
        var el = jQuery(this);
        
        if(el.attr('rel') == undefined) 
        {
            el.attr('rel', el.val()).addClass(settings.blurClass);
        }
        
        
        el.focus(function() 
        {
            
            if(el.val() == el.attr('rel')) 
            {
                el.val('').removeClass(settings.blurClass).addClass(settings.activeClass);
            }
            
        });
        
        el.blur(function() 
        {
            
            if(el.val() == '') 
            {
                el.val(el.attr('rel')).removeClass(settings.activeClass).addClass(settings.blurClass);
            }
        });
    });
    
    return jQuery;
};

})(jQuery);

//
// Same as PHP ctype_alnum().
//
function ctype_alnum(text) 
{
    if (typeof text !== 'string') 
    {
        return false;
    }

    return text.match(/^[a-zA-Z0-9]*$/)
}

//
// Escape quotes. 
//
// Used for sending string to a from JS 
// function to another.  I SHOULD FIND ANOTHER SOLUTION assi
//
function q_escape(str)
{                               
    str = str.replace(/\\/g,'\\\\');
    str = str.replace(/'/g,"&acute;");
    str = str.replace(/\"/g,'&quot;');
    str = str.replace(/\0/g,'\\0');    
    
    return str;
}

function q_unescape(str)
{
    str = str.replace(/&acute;/g,'\'');
    str = str.replace(/\\'/g,'\'');
    str = str.replace(/&quot;/g,'"');
    str = str.replace(/\\0/g,'\0');
    str = str.replace(/\\\\/g,'\\');
    
    return str;
}

//
// Transforms embedded URL to iframe.
//
// If input is not a youtube / flickr URL, it is 
// assumed input is already an embedding code,  
// and therefore input is returned untouched,
// apart of width that is being adjusted to
// template.
//
function embedded_url_to_embed_code(url, width, height)
{    
    url = q_unescape(url);
    var code = url;       
    var pattern;
    
    var str_youtube_single_movie_url = "youtube.com\/watch\?v=";
    var regex_flickr_set_url = /flickr\.com\/photos\/([^@]*).*\/sets\/([^\/]*)/;
    var regex_image_url = /^http.*\.[jpg|png|gif]/;
    var regex_object = /<object/;
    var regex_iframe = /<iframe/;
    
    var do_chg_height = false;

    //
    // Case YouTube playlist.
    //
    if (url.indexOf('view_play_list') != -1)
    {
        var playlist_id = url.replace("http://www.youtube.com/view_play_list?p=", "");
        
        if (ctype_alnum(playlist_id))
        {
            code = '<object width="480" height="385"><param name="movie" value="http://www.youtube.com/p/'+playlist_id+'&hl=en_US&fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/p/'+playlist_id+'&hl=en_US&fs=1" type="application/x-shockwave-flash" width="480" height="385" allowscriptaccess="always" allowfullscreen="true"></embed></object>';
            
            do_chg_height = true;
        }
    }
    
    //
    // Case YouTube single video.
    //
    else if (url.indexOf(str_youtube_single_movie_url) != -1)
    {
        var pattern = str_youtube_single_movie_url;
        
        if
        (
            (url.indexOf(pattern) != -1) && 
            (url.indexOf(pattern) == url.lastIndexOf(pattern))
        )
        {
            var movie_id = url.replace(/.*youtube\.com\/watch\?v=/, "");

            code = '<object width="480" height="385"><param name=wmode value=transparent></param><param name="movie" value="http://www.youtube.com/v/'+movie_id+'&hl=en_US&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/'+movie_id+'&hl=en_US&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385" wmode=transparent></embed></object>';
            
            do_chg_height = true;
        }
    }
    
    
    //
    // Case Flickr set.
    // http://www.flickr.com/photos/dan65/sets/72157594270655908/
    //
    else if (url.match(regex_flickr_set_url))
    {
        var ary = url.match(regex_flickr_set_url);
        var user_id = ary[1];
        var set_id = ary[2];
    
        code = '<iframe align="center" src="http://www.flickr.com/slideShow/index.gne?group_id=&user_id='+user_id+'@N00&set_id='+set_id+'" frameBorder="0" width="480" height="385" scrolling="no"></iframe>';
        
        do_chg_height = true;
    }
    
    //
    // Case object / iframe - remove code before
    // and after the object / iframe code.
    //
    // Read more about javascript regex here:
    // http://www.evolt.org/article/Regular_Expressions_in_JavaScript/17/36435/
    //
    else if (url.match(regex_object))
    {
        code = code.replace(/.*(<object.*<\/object>).*/, '$1');
    }
    
    else if (url.match(regex_iframe))
    {
        if ( ! url.match('maps.google.com'))
        {
            code = code.replace(/.*(<iframe.*<\/iframe>).*/, '$1');
        }
    }
    
    //
    // Add transparency.
    //
    if (url.match(/<object/))
    {
        code = code.replace('<param name=wmode value=transparent></param>', '');
        code = code.replace(/(<object[^>]*>)/, '$1<param name=wmode value=transparent></param>');
    }
    
    if (url.match(/<embed/))
    {
        code = code.replace(' wmode="transparent"', '');
        code = code.replace(" wmode='transparent'", '');
        code = code.replace('<embed', '<embed wmode="transparent"');
    }
    
    //
    // Change Picasa background color.
    //
    code = code.replace('RGB=0x000000', 'RGB=0xFFFFFF');
    
    //
    // Constrain dimensions.
    //                     
    if (width == null)
    {
        width = BLOCK_WIDTH;
    }

    if (height == null)
    {
        height = parseInt(BLOCK_WIDTH * 295 / 370); // 305
    }
    
    code = code.replace(/border-right-width:\s*\d+px;?/gi, '');
    code = code.replace(/border-left-width:\s*\d+px;?/gi, '');
    code = code.replace(/border-top-width:\s*\d+px;?/gi, '');
    code = code.replace(/border-bottom-width:\s*\d+px;?/gi, '');
    
    code = code.replace(/width="\d+"/gi, 'width="'+width+'"');
    code = code.replace(/width:\s*\d+px/gi, 'width: '+width+'px');
    
    if (height != null)
    {
        code = code.replace(/height="\d+"/gi, 'height="'+height+'"');
        code = code.replace(/height:\s*\d+px/gi, 'height: '+height+'px');
    }
    
    //
    // Return output.
    //
    return code;
}

//
// The following two functions are used to decode
// Hebrew characters from JSON object. When generating
// the JSON oject, the opposite of these two functions
// was used, in order to preserve the Hebrew characters.
//

/**
 * Decodes string using MIME base64 algorithm
 * @see http://phpjs.org/functions/base64_decode
 */
function base64_decode( data ) {
    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, dec = "", tmp_arr = [];

    if (!data) {
        return data;
    }

    data += '';

    do {  // unpack four hexets into three octets using index points in b64
        h1 = b64.indexOf(data.charAt(i++));
        h2 = b64.indexOf(data.charAt(i++));
        h3 = b64.indexOf(data.charAt(i++));
        h4 = b64.indexOf(data.charAt(i++));

        bits = h1<<18 | h2<<12 | h3<<6 | h4;

        o1 = bits>>16 & 0xff;
        o2 = bits>>8 & 0xff;
        o3 = bits & 0xff;

        if (h3 == 64) {
            tmp_arr[ac++] = String.fromCharCode(o1);
        } else if (h4 == 64) {
            tmp_arr[ac++] = String.fromCharCode(o1, o2);
        } else {
            tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
        }
    } while (i < data.length);

    dec = tmp_arr.join('');
    dec = this.utf8_decode(dec);
    return dec;
}

/**
 * Converts a UTF-8 encoded string to ISO-8859-1
 * @see http://phpjs.org/functions/utf8_decode
 */
function utf8_decode ( str_data ) {
    var tmp_arr = [], i = 0, ac = 0, c1 = 0, c2 = 0, c3 = 0;

    str_data += '';

    while ( i < str_data.length ) {
        c1 = str_data.charCodeAt(i);
        if (c1 < 128) {
            tmp_arr[ac++] = String.fromCharCode(c1);
            i++;
        } else if ((c1 > 191) && (c1 < 224)) {
            c2 = str_data.charCodeAt(i+1);
            tmp_arr[ac++] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
            i += 2;
        } else {
            c2 = str_data.charCodeAt(i+1);
            c3 = str_data.charCodeAt(i+2);
            tmp_arr[ac++] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
            i += 3;
        }
    }

    return tmp_arr.join('');
}

function decode_from_json(str)
{
    return utf8_decode(base64_decode(str));
}

//
// Set / Return form field value.
//
function get_form_field(form_name, field_name)
{
    return $(':input[name='+field_name+']', document.forms[form_name]).val();
}

function set_form_field(form_name, field_name, value)
{
    $(':input[name='+field_name+']', document.forms[form_name]).val(value);
}

//
// Replaces double and single quotes with their 
// HTML name or number.
//
// Used for displaying double and single quotes 
// inside JS field, when the command
//
//    document.forms['...'].field_name.value = value
//
// is delivered as HTML string. 
// 
//  See usage example in display_gallery_tns().
// 
function quotes_to_html(str)
{
    str = str.replace("'", "\&acute;");
    str = str.replace('"', "\&quot;");
    str = str.replace("\r\n", "");
    str = str.replace("\r", "");
    str = str.replace("\n", "");
    
    return str;
}
 
//
// Generetes HTML of select options, based
// on input 2-dim array (ID, val).
//
function gen_html_select(options, sel_val)
{
    var val, text, sel_str;
    var html = '';
    
    for (var val in options)
    {
        text = options[val];
        
        if (sel_val)
        {
            sel_str = (val == sel_val) ? 'selected="selected"' : '';
        }
        
        else
        {
            sel_str = '';
        }
        
        html += '<option value="'+val+'" '+sel_str+'>'+text+'</option>';
    }
    
    return html;
}

//
// Returns the number of displayed table rows.
//
function get_num_displayed_table_rows(tbody_id)
{
    var num_rows = 0;
    
    $('#'+tbody_id+' tr').each
    (
        function()
        {
            if ( ! $(this).is(':hidden'))
            {
                num_rows++;
            }
        }
    );
    
    return num_rows;
}

//
// Convers timestamp to date.
//
function ts_to_date(ts)
{
    var date_obj = new Date(ts * 1000);
    return date_obj.toDateString(); //.toLocaleString()
}

//
// Toggles checkbox.
//
function toggle_checkbox(id)
{
    $('#'+id).attr('checked', ! $('#'+id).attr('checked'));
}

//
// Draws a pie.
//
function draw_pie(div_id, data, num_votes)
{
    $.plot($('#'+div_id), data, 
    {
        series: {
            pie: { 
                show: true,
                radius: 1,
                label: {
                    show: true,
                    radius: 2/3,
                    formatter: function(label, series){
                        return '<div class="pie_label">'+label+'<br/>'+Math.round(series.percent)+'%</div>';
                    },
                    threshold: 0.1,
                    background: { 
                        opacity: 0.5,
                        color: '#000'
                    }        
                }
            }
        },
        grid: {
            hoverable: false,
            clickable: true
        },
        legend: {
            show: false
        }
    });
    
    $('#'+div_id).bind('plotclick', function(event, pos, obj){my_alert(q_unescape(obj.series.label)+': '+Math.round(num_votes * obj.series.percent / 100)+' '+translate('votes'))});
}

function pie_click(event, pos, obj) 
{
    if ( ! obj)
    {
        return;
    }

    percent = parseFloat(obj.series.percent).toFixed(2);
    alert(''+obj.series.label+': '+percent+'%');
}

//
// Filters library name:
//
// . Transform spaces into underscore.
// . Filter out invalid characters.
//
function filter_library_name(field)
{
    var lib_name = field.value;
    var org_lib_name = lib_name;
    
    lib_name = lib_name.replace(/\s+/g, "_");
    lib_name = lib_name.replace(/[^a-zA-Z0-9_]/, "");
    
    if (org_lib_name != lib_name)
    {
        field.value = lib_name;
    }
}

function is_handheld()
{
    var user_agent = navigator.userAgent.toLowerCase();
    
    return (user_agent.match(/android/i) ||
        user_agent.match(/webso/i) ||
        user_agent.match(/iphone/i) ||
        user_agent.match(/ipod/i) ||
        user_agent.match(/blackberry/i)
    );
}
