//////////////////////////////////////////////////////////////////////////
//
// 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: 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.length < 6 )
   {
      return false;
   }
   else
   {
      return true;
   }
}
  
  function checkEmailValue( value, ID )
   {
      if ( !isValidEmailString( value ) ) 
      { 
         displayErrorBoxEmail();
         showError( ID );
         return false;
      } 
      else 
      { 
         hideErrorBoxEmail();
         showOK( ID );
         return true;
      }
   }
   
   function checkStringValue( value, ID )
   {
      if ( !isValidNameString( value ) ) 
      { 
         displayErrorBoxDisplayName();
         showError( ID );
         return false;
      } 
      else 
      { 
         hideErrorBoxDisplayName();
         showOK( ID );
         return true;
      }
   }
   
   function checkPasswordReentry()
   {
      if ( document.getElementById( "password1" ).value == document.getElementById( "password2" ).value )
      {
         var returnVal = true;
         
         if ( document.getElementById( "password1" ).value == '' )
         { 
            hideErrorBoxPassword();
            hide( 'password1' );
            hide( 'password2' );
            return returnVal;
         }
         
         if ( !isValidPasswordString( document.getElementById( "password1" ).value ) )
         {
            displayErrorBoxPassword();
            showError( "password1" );
            returnVal = false;
         }
         else
         {
            showOK( "password1" );
         }
         
         if ( !isValidPasswordString( document.getElementById( "password2" ).value ) )
         {
            displayErrorBoxPassword();
            showError( "password2" );
            returnVal = false;
         }
         else
         {
            showOK( "password2" );
         }
         
         if ( returnVal )
         {
            hideErrorBoxPassword();
         }
         return returnVal;  
      } 
      else
      {
         displayErrorBoxPassword();
         showError( "password1" );
         showError( "password2" );
         return false;
      }
   }
   
   function hide( ID )
   {
      showOK( ID );
      document.getElementById( ID + "OK" ).style.display = 'none';
   }
   
   function showError( ID )
   {
      document.getElementById( ID + "Invalid" ).style.display = 'inline';
      document.getElementById( ID + "OK" ).style.display = 'none';
      
      Element.addClassName( ID + "Field", "invalidField" );
      Element.addClassName( ID, "invalidEntry" );
   }
   
   function showOK( ID )
   {
      document.getElementById( ID + "Invalid" ).style.display = 'none';
      document.getElementById( ID + "OK" ).style.display = 'inline';
      
      Element.removeClassName( ID + "Field", "invalidField" );
      Element.removeClassName( ID, "invalidEntry" );
  }


//////////////////////////////////////////////////////////////////////////
// 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);
            }
         };
      }
   });
};