

var Validators = 
{
   Version: "1.0.0"
}

//////////////////////////////////////////////////////////////////////////
//
// Javascript Input/Output Validator/Encoder
//
//////////////////////////////////////////////////////////////////////////

// Whitelist pattern used in multiple places
var WHITELISTPATTERN = /^([0-9a-zA-Z]|\.|\(|\)|,|!|\$|'| |_|-)+?$/;

//////////////////////////////////////////////////////////////////////////
// Function: isValidForUrl( str )
// Accepts: String to validate
// Returns: true on valid, false otherwise
//
// Test to see if a string is an acceptable pattern for passing
// in URLs: playlist/folder titles, etc.
// DO NOT call this function directly call the specific function.
//////////////////////////////////////////////////////////////////////////
function isValidTitle( titleToValidate )
{
   // Trailing periods break URIs
   var lastChar = titleToValidate.charAt( titleToValidate.length - 1 );
         
   if ( lastChar == "." )
   {
      return false;
   }

   // Check the length
   if ( titleToValidate.length < 1 || titleToValidate.length > 128 )
   {
      return false;
   }

   // Try to match whitelist characters
   return WHITELISTPATTERN.test(titleToValidate);
   
} // end isValidTitle()

//////////////////////////////////////////////////////////////////////////
// Function: isValidFolderTitle( str )
// Accepts: String to validate
// Returns: true on valid, false otherwise
//
// Determine validity of a folder title by matching on
// whitelisted characters and testing the length.
//////////////////////////////////////////////////////////////////////////
function isValidFolderTitle( toValidate )
{
   return isValidTitle( toValidate );
}

//////////////////////////////////////////////////////////////////////////
// Function: isValidMediaSetTitle( str )
// Accepts: String to validate
// Returns: true on valid, false otherwise
//
// Determine validity of a given media set title by matching on
// whitelisted characters and testing the length.
//////////////////////////////////////////////////////////////////////////
function isValidMediaSetTitle( mediaSetToValidate )
{
   // Check the length
   if ( mediaSetToValidate.length < 1 || mediaSetToValidate.length > 128 )
   {
      return false;
   }

   // Try to match whitelist characters
   return WHITELISTPATTERN.test( mediaSetToValidate );

} // end isValidMediaSetTitle

//////////////////////////////////////////////////////////////////////////
// Function: isValidPlaylistTitle( str )
// Accepts: String to validate
// Returns: true on valid, false otherwise
//
// Determine validity of a playlist title by matching on
// whitelisted characters and testing the length.
//////////////////////////////////////////////////////////////////////////
function isValidPlaylistTitle( toValidate )
{
   return isValidTitle(toValidate);
}

//////////////////////////////////////////////////////////////////////////
// Function: isValidInput( str, [bool] )
// Accepts: String to validate, bool allow html or not (e.g. comments)
// Returns: true on valid, false otherwise
//
// Test to see if a string is an acceptable pattern for use in form
// fields in screencast.com.
//
//////////////////////////////////////////////////////////////////////////
function isValidInput ( toValidate, allowLimitedHtml )
{
   if ( allowLimitedHtml )
   {
      // strip out supported html causing the next test to pass
      var allowedHtmlExp = /<b>|<\/b>|<strong>|<\/strong>|<u>|<\/u>|<i>|<\/i>|<em>|<\/em>|<br>|<br\/>|<br \/>/g;
      toValidate = toValidate.replace( allowedHtmlExp, '' );
   }

   // Look for remaining unsupported HTML - should allow < or > though for math
   var htmlRegExp = /<\S.*?>/;
   if ( htmlRegExp.test( toValidate ) )
   {
      return false;
   }
   
   return true;

}

function isValidUri(toValidate)
{
    var uriRegExp = new RegExp("^[a-z]+://([a-z0-9]+\\.)?[^\\.\\?/\\\\]+\\.[a-z0-9]+[^\\?]*(\\?.*)?$", "i");
    return uriRegExp.test( toValidate );
}

//////////////////////////////////////////////////////////////////////////
// Function: encodeForUrl( str )
// Accepts: string to encode
// Returns: encoded string
//
// Encode strings to be passed in a URL
//
//////////////////////////////////////////////////////////////////////////
function encodeForUrl ( toEncode )
{
    return encodeURI(toEncode);
}

//////////////////////////////////////////////////////////////////////////
// Function: decodeForUrl( str )
// Accepts: string to decode
// Returns: decoded string
//
// Dencode strings to be passed in a URL
//
//////////////////////////////////////////////////////////////////////////
function decodeForUrl ( toDecode )
{
   return unescape( toDecode )
}

//////////////////////////////////////////////////////////////////////////
// Function: encodeInput( str )
// Accepts: string to encode
// Returns: encoded string
//
// Encode strings for form data
//
//////////////////////////////////////////////////////////////////////////
function encodeInput ( toEncode )
{
    return encodeURIComponent(toEncode);
}

//////////////////////////////////////////////////////////////////////////
// Function: decodeInput( str )
// Accepts: string to decode
// Returns: decoded string
//
// Decode strings for form data
//
//////////////////////////////////////////////////////////////////////////
function decodeInput ( toDecode )
{
   return unescape( toDecode );
}

//////////////////////////////////////////////////////////////////////////
// Function: encodeForHTML( str )
// Accepts: string to encode
// Returns: decoded string
//
// Encode strings for use in HTML
//
//////////////////////////////////////////////////////////////////////////
function encodeForHTML ( toEncode )
{
    return toEncode.replace(/&/g, '&amp;').
    replace(/>/g, '&gt;').
    replace(/</g, '&lt;').
    replace(/"/g, '&quot;');
}

//////////////////////////////////////////////////////////////////////////
// Function: decodeForHTML( str )
// Accepts: string to decode
// Returns: decoded string
//
// Decode strings from encoded HTML
//
//////////////////////////////////////////////////////////////////////////
function decodeForHTML ( toDecode )
{
    return toDecode.replace(/&amp;/g, '&').
    replace(/&gt;/g, '>').
    replace(/&lt;/g, '<').
    replace(/&quot;/g, '"');
}

//////////////////////////////////////////////////////////////////////////
// Function: isValidEmailString( str )
// Accepts: email address
// Returns: true if valid, flase otherwise
//
// Check for valid email address pattern
//
//////////////////////////////////////////////////////////////////////////
function isValidEmailString( value )
{
   var reg = /^([a-zA-Z0-9_]|\-|\.)+@(([a-zA-Z0-9_]|\-)+\.)+[a-zA-Z]{2,4}$/;

   if ( !reg.test( value ) )
   {
      return false;
   }

   if ( value.length < 6 || value.length > 129 )
   {
      return false;
   }

   return true;
}

//////////////////////////////////////////////////////////////////////////
// Function: isValidNameString( str )
// Accepts: display name
// Returns: true if valid, flase otherwise
//
// Check for valid display name pattern
//
//////////////////////////////////////////////////////////////////////////   
function isValidNameString( value )
{
   var reg = /^([A-Za-z])([0-9A-Za-z\._\-]){0,18}([0-9A-Za-z_\-]){1}$/;

   return reg.test( value );
}

//////////////////////////////////////////////////////////////////////////
// Function: isValidPasswordString( str )
// Accepts: password
// Returns: true if valid, flase otherwise
//
// Check for valid password pattern
//
//////////////////////////////////////////////////////////////////////////      
function isValidPasswordString( value )
{
   if (value == null || value.length < 6 || value.length > 20)
   {
      return false;
   }
   
   var htmlRegExp = /<\S.*?>/;
   if (htmlRegExp.test(value))
   {
      return false;
   }

   return true;
}

//////////////////////////////////////////////////////////////////////////
// Function: isValidISO639LanguageCode( str )
// Accepts: ISO 639 Language Code
// Returns: true if valid, false otherwise
//
// Check for valid ISO 639 language pattern.
// For more information on valid ISO 639 codes
// see this url: http://www.loc.gov/standards/iso639-2/php/code_list.php
//
//////////////////////////////////////////////////////////////////////////
function isValidITunesLanguageCode(value)
{
    var reg = /^([A-Za-z]){2,3}(-([A-Za-z]){2,3}){0,1}$/;

    return reg.test(value);
}

// We can only validate that the license key is of the proper length in JavaScript
// right now
function isValidLicenseKey(value) 
{
    var reg = /^(([0-9A-Za-z]){5}-){4}([0-9A-Za-z]){5}$/;

    return reg.test(value);
}

//We only care about the format, we do not check if it's an actual Google Analytics Key
function isValidGoogleAnalyticsKey(value) {
   var reg = /^UA-[0-9]+-[0-9]+$/;

   return reg.test(value) || value === '';
}

//////////////////////////////////////////////////////////////////////////
// Function: maxLength( int )
// Accepts: maximum length
// Returns: true if the textarea is under the maximum length.
// Returns false otherwise
//
// This function allows you to set a MaxLength on the 
// textarea/ASP:TextBox MultiLine control.
// Call it by placing the code below in the javascript somewhere on the page:
//        jQuery("#ID_of_textarea").maxLength(4000);
//
//////////////////////////////////////////////////////////////////////////   

jQuery.fn.maxLength = function(max)
{
   this.each(function()
   {
      //Get the type of the matched element
      var type = this.tagName.toLowerCase();
      
      //If the type property exists, save it in lower case
      var inputType = this.type ? this.type.toLowerCase() : null;
      
      //Check if is a input type=text OR type=password
      if (type == "input" && inputType == "text" || inputType == "password")
      {
         //Apply the standard maxLength property
         this.maxLength = max;
      }
      //Check if the element is a textarea
      else if (type == "textarea")
      {
         //Add the key press event
         this.onkeypress = function(e)
         {
            //Get the event object (for IE)
            var ob = e || event;
            
            //Get the code of key pressed
            var keyCode = ob.keyCode;
            
            //Check if it has selected text
            var hasSelection = document.selection ? document.selection.createRange().text.length > 0 : this.selectionStart != this.selectionEnd;
            
            //return false if we are the textbox is at the limit, but allow the arrow keys, backspace, and delete 
            return !(this.value.length >= max && (keyCode > 50 || keyCode == 32 || keyCode == 0 || keyCode == 13) && !ob.ctrlKey && !ob.altKey && !hasSelection);
         };
         //Add the key up event
         this.onkeyup = function()
         {
            //If the keypress check fails and allows the user to write more text than the limit, this event will remove it
            //An example of this is when the user pastes text that contains more than the maximum allowed characters into the textarea
            if (this.value.length > max)
            {
               this.value = this.value.substring(0, max);
            }
         };
      }
   });
};
