/*!
 * ty JavaScript Library v1.0.1 
 * http://www.tnpfk.com/
 * 
 * Copyright (c) Tyler Beck
 * Last Revision: Thursday, July 2nd, 2009
 * Revisions: 104
 * Pages: 1 - 79
!*/ 

/*

 ty JavaScript Library - Powerful JS
 Copyright (C) 2009  Tyler Beck
 Open-Source JavaScript Library
 
 * @ This program is free software: you can redistribute it and/or modify
 * @ it under the terms of the GNU General Public License as published by
 * @ the Free Software Foundation, either version 3 of the License, or
 * @ (at your option) any later version.

 * @ This program is distributed in the hope that it will be useful,
 * @ but WITHOUT ANY WARRANTY; without even the implied warranty of
 * @ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * @ GNU General Public License for more details.

 * @ You should have received a copy of the GNU General Public License
 * @ along with this program.  If not, see <http://www.gnu.org/licenses/>.

 * <OWNER> = Tyler R. Beck
 * <ORGANIZATION> = Team Network for Public Free Knowledge
 * <YEAR> = 2006

 * Copyright (c) 2009, Tyler R. Beck
 * All rights reserved.

 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:  Redistributions of source 
 * code must retain the above copyright notice, this list of conditions and the following disclaimer.  
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 
 * and the following disclaimer in the documentation and/or other materials provided with the distribution.  
 * Neither the name of the Team Network for Public Free Knowledge nor the names of its contributors may be 
 * used to endorse or promote products derived from this software without specific prior written permission.
 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

//////////////////////////////////////////////////////////
// * Current functions in development and are not working:
// * $.obj.fx.animate(); - still in development.
//////////////////////////////////////////////////////////

/////////////////////////////////////////////////////
// * Documentation for ty Javascript Library is currently not supported, but will
// * be added in the future once the Docs are setup on my site. Thank you for being
// * patient, and all questions can be answered on http://www.tnpfk.com/
// * NOTE: plug-ins are supported in the ty Library, to find out more information
// * please check-out the extend function provided by the ty Library.
// * 
// * NOTE: ty Library takes advantages of other scripting methods that are used
// * within the library.  these methods include the use of object literal
// * programming, AJAX (asynchronous javascript and xml), AJAST (asynchronous  
// * javascript and script tags).
// * 
// * *** GOOGLE GEARS *** - http://code.google.com/apis/gears/
// * Copyright 2007, Google Inc.
// * 
// * ty Library supports Google Gears (TM). Google Gears is an open-source project
// * that enables support for more powerful web applications , by adding new features
// * to the browser.  Support for some of the primary and core usages of Gears has been
// * added to the ty Lirary; NOTE: Google Gears is a browser add-on; and must be installed
// * like Adobe Flash to be used.
// *
// * ty Supports the following functions and methods:
// * $ - function : extend ( fn, [name] ) return Boolean / Array
// * $ - function : ready ( mainFn ); return isReady Boolean
// * $ - function : o ( obj ); return Boolean / Object
// * $ - function : events ( obj, type, callback, [detach] ); return Boolean
// * $ - function : cookie ( name, value, options ); return Void / String / Boolean
// * $ - function : ajax ( ajaxOptions ); return Void
// * $ - function : ajast ( src, fn ); return Void
// * $ - function : swfit ( src, id, width, height, version, express ); return Void
// * $ - function : obj.fx.stop ( ); return Void
// * $ - function : obj.fx.animate ( obj, arrParams, time ); return Boolean 
// * $ - function : obj.fx.expand ( obj, method ) return Boolean
// * $ - function : obj.fx.collapse( obj, method ) return Boolean
// * $ - function : obj.fx.slide ( obj, ease, type, sec, autoStart ); return Boolean
// * $ - function : obj.fx.hide ( context, tags, show ); return Boolean
// * $ - function : obj.fx.show ( context, tags ); return Boolean
// * $ - function : obj.fx.hover ( obj, data1, data2 ); return Boolean
// * $ - function : obj.fx.fade ( obj, fadeFrom, fadeTo, msPer, callback); return Boolean
// * $ - function : obj.fx.toggle ( callback1, callback2 ); return Boolean
// * $ - function : obj.fx.drag.attach ( dragElement ); return Boolean
// * $ - function : obj.fx.drag.detach ( dragElement ); return Boolean
// * $ - function : obj.fx.drag.dragger.init ( o, oRoot, minX, maxX, minY, 
// * $ - maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper ); return Boolean
// * $ - function : obj.css ( obj, cssBlock ); return Boolean 
// * $ - function : obj.getElementsByClass ( searchClass, node, tag ); return Array
// * $ - function : obj.getStyle( id, styleProp ); return String / Number
// * $ - function : obj.attr ( obj, data, value ); return Boolean / Object
// * $ - function : obj.alpha ( obj, value ); return Boolean / Number
// * $ - function : obj.myX ( obj ); return Boolean / Number
// * $ - function : obj.myY ( obj ); return Boolean / Number
// * $ - function : obj.replaceWith ( obj, newElement ); return Boolean
// * $ - function : utils.bwsr.agent ( ); return Object
// * $ - function : img.preload ( src ); return Void
// * $ - function : img.valid ( src ); return Boolean
// * $ - function : filter.inx ( tagtype, index, dataObject, [defaultSet] ); return Boolean
// * $ - function : filter.forming ( form, typeObject ); return Object / Boolean
// * $ - function : arrays.inArray ( value, array, [sensitive] ); return Boolean
// * $ - function : arrays.shuffle ( object ); return Boolean / Array
// * $ - function : arrays.each ( object, callback ); return callBack / Void
// * $ - function : arrays.isArray ( object ); return Boolean
// * $ - function : arrays.unique ( object ); return Array
// * $ - function : arrays.serialize ( object ); return String
// * $ - function : arrays.iterateObj ( object ); return Array
// * $ - function : arrays.merge ( a, b ) ; return Array
// * $ - function : arrays.flat ( array); return Array
// * $ - function : str.trim ( str ); return String
// * $ - function : str.isDate ( str ); return Boolean
// * $ - function : str.containsWildChars ( str ); return Boolean
// * $ - function : str.contiansNumerics ( str ); return Boolean
// * $ - function : str.utf8_encode ( string ); return UTF-8 String;
// * $ - function : str.base64_decode ( data ); return String
// * $ - function : convert.RGBFromHex ( hexCode ); return Boolean / Array
// * $ - function : convert.HEXFromRGB ( red, green, blue ); return Boolean / String
// * $ - function : widgets.use ( id, widgetName, [params] ); return Widget 
// * $ - function : widgets.destroy ( id ) ; return Boolean
// * $ - function : gears.init ( fn, initGears ); return Void
// * $ - function : gears.installed ( options ); return Boolean
// * $ - function : gears.geolocate ( callBack, installOptions ); return fn(Object)
// * $ - function : gears.upload ( multipleFiles, putURL, fnProgress, fnComplete, installOptions ); return Void
// * $ - function : gears.resource.create ( storeName, installOptions ); return Boolean
// * $ - function : gears.resource.remove ( storeName, installOptions ); return Boolean
// * $ - function : gears.resource.findPageResources ( self ); return Array
// * $ - function : gears.resource.capture ( storeName, captureFiles, fnCaptured, installOptions ); return Boolean / Void
// * $ - function : gears.resource.uncapture ( storeName, captureFiles, installOptions ); return Void
/////////////////////////////////////////////////////

//////////////////////////////////////////////////////////
// * note: when a function or object; etc, calls for use
// * of an easing equation, you can use one of the following
// * in ty Library; please read the descriptions for more
// * information on exactly what each tween does.
// * the default tween if none is specified for any function 
// * that uses tweener, is easeNone; which just tweens regulary 
// * with no effect.
// *
// * Tween.backEaseIn - tweens backwards, then forwards to finish.
// * Tween.backEaseOut - tweens forwards, then tweens backwards to finish.
// * Tween.backEaseInOut - combines both easing in, and out backwards.
// * Tween.elasticEaseIn - elastic forced downwards; which shoots upwards.
// * Tween.elasticEaseOut - elastic forced upwards; which shoots downwards.
// * Tween.elasticEaseInOut - elastic forced both ways; which shoots both ways.
// * Tween.bouncEaseIn - bounces upwards till coming to a complete stop.
// * Tween.bouncEaseOut - bounces downwards till coming to a complete stop.
// * Tween.bounceEaseInOut - bounces both ways till coming to a stop.
// * Tween.regularEaseIn - slowly eases in towards finishing fast.
// * Tween.regularEaseOut - eases in fast towards finishing slow.
// * Tween.regularEaseInOut - starts off slow; then faster; then slow again
// * Tween.strongEaseIn - starts off real slow; and ends fast
// * Tween.strongEaseOut - starts off real fast; and ends slow
// * Tween.strongEaseInOut - starts off slow; then fast; then slow.
//////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////
// * ty Library Widgets - XHTML / CSS / JavaScript 
// * 
// * ty Widgets allow you to create easy graphical user  interfaces or user interfaces 
// * that allow for a more advanced experience. Below are the different widgets that 
// * are supported and the predefined themes (or skins) that come with them.  if you
// * would like more information; please visit the tnpfk website http://www.tnpfk.com/
// * 
// * NOTE: some widgets may not work in every browser; most all of them work across 
// * the board; but some still have some bugs that are being worked out with browsers.
// *
// * Below is a list of widgets that are provided by ty Library
// *
// * Button - basic button that provides simplistic functionality; to more complex views.
// * -> Button : Simple - a simple button that allows for the same functionality as a regular button.
// * -> Button : Dropdown - provides a simple button; that uses a dropdown menu to display anything.
// * Inline Edit Box - an inline edit box is a way to allow for direct editing of text on the screen,
// * such as if you have a heading element; you can click it and edit it directly through a textbox.
// * Tab Container - a tab container is a allows you to switch through different elements to view
// * different data in the same container without having to cram it all into one thing.
// * Dialog Box - a dialog box works like an alert; but creates a background with a regular dialog
// * where you can put as much information as you want including forms, images, and much more.
// * Title Pane - title panes allow for easy hiding and showing of data
//////////////////////////////////////////////////////////

var ty_version = "1.0.1";
var ty = new Object();

////////////////////////////////////////
// GLOBAL VARIABLES WHICH ARE CHANGED //

// stops all animations / effects / etc.
var animeStop = new Boolean(false);
// slides array, which contains an array of the object and 
// the maximum height used previously; which is stored.
var slidesArray = new Array();
// the current toggle states for objects that
// have been registered with the toggle effect
var toggleStates = new Array();
// the DOM (Document Object Module) is loaded.
var isReady = new Boolean(false);
var lastButtonWidget = null;
var lastCallBack = null;
////////////////////////////////////////

ty = {
  
 // these are global variables that can be accessed for variety of different
 // things in the ty Library.  these help you automatically the fill the data
 // without typing it.  to access globals: $.gl.ALL(); or _.gl.ALL();
 gl: {
  
  // the following 3 constants are for the hide and show commands
  // available in the object effects portion of this library.
  ALL: function(){return "all";},
  FIRST: function(){return "first";},
  LAST: function(){return "last";},
  DEFAULT_SEARCH: function(){return "div";},
  
  // slide animation commands
  CLOSE: function(){return 0;},
  OPEN: function(){return 1;},
  
  // the following commands are for the use with 
  // the collapse function in the object effects
  FX_HEIGHT: function(){return "height";},
  FX_DISPLAY: function(){return "display";},
  
  // tells the function what we want to return
  // the data back in; an array or an object.
  ARRAY: function(){return "array";},
  OBJECT: function(){return "object";},
  
 },
 
 // return the current version that we are using of ty.
 version: ty_version,
 author: "Tyler Beck",
 
 // this function allows for the support of plug-ins by extending 
 // the ty Library.  This will allow you to call functions internally
 // from ty Library and allow the ability to extend the entire Library.
 // how-to-use: to extend one of your own plugins to the ty Library, 
 // you can simply add one function or add an entire object of functions.
 // example 1.) $.extend(fn); // extends the function to the library core object
 // example 2.) $.extend({fn,fn2,fn3}); // extends multiple functions to the library
 // the name parameter is optional; and is only to be used when extending 1 function
 extend : function(fn, name){
  
  // if the given fn object is a function then all we have to do is 
  // add it to the library and then we are all done. 
  if(fn != null && (typeof fn.constructor.toString() == 'function')){ 
   // the function given already exists ... we cannot add this function.
   for(fnx in ty){ 
    if(fnx.toLowerCase() == name.toLowerCase()) return false; 
   };
   
   ty[name] = fn; // extend the given function with the given name.
   return true; // we've successfully extended this function to the Library
  };
  
  var ret = new Array(); // returned booleans
  var exists = new Boolean(false);
  // if we have gotten past this point; this means that there is probably
  // more than one function that we are going to add to the library.
  // NOTE: this part of this function returns an array with values of 
  // which functions were successfully added, and which were not.  they 
  // go in order from 0 to the length of the object.
  for(functs in fn){ 
   if((fn[functs] != null) && (typeof(fn[functs].constructor.toString() == 'function'))){
    
	for(fnx in ty){ // check if the function already exists
	  if(fnx.toLowerCase() == functs.toLowerCase()){ 
	   ret.push(false); // add that it exists to the array
	   exists = true; // the function already exists...
	};};
	
	// the function does not exist and we can add the function to
	// the library without conflictions...then reset the exists
	if(exists == false){ ret.push(true); ty[functs] = fn[functs] };
	// reset the exists boolean.
	exists = false;
	 
   }; // if 
  }; // for
  
  return ret;
  
 },
 
 // this function is a shortcut for the function checkObjectTag, and 
 // just extends it to the library so you can easily convert id-names
 // to objects instead of typing out the document object.
 o: function(obj){ return(checkObjectTag(obj)); },
 
 // swfit is a quick and easy one-line function that allows you to add flash
 // content dynamically and semantically; it uses the SWFObject provided
 // by MIT; for more info please visit: http://code.google.com/p/swfobject/
 swfit: function(src, id, width, height, version, express){
  if(express==null||express=="undefined") express = "expressInstall.swf";
  if(version==null||version=="undefined") version = "9.0.0";
  swfobject.embedSWF(src, id, width, height, version, express);
 },
 
 // returnElement allows you to return the Object that triggered an 
 // event; most likely the case will come from a Mouse Event.  this 
 // function will help find the Object that triggered it in all browsers.
 returnElement: function(e){ 
  if(!e) var e = window.event; if(e.target) curObj = e.target;
  else if(e.srcElement) curObj = e.srcElement; 
  if(curObj.nodeType==3) curObj = obj.parentNode;
  return(curObj); // return the object.
 },
 
 // this function is a replacement to the onload method, which allows faster
 // loading of the document and faster-use of the objects which are on the 
 // document.  note: this browser is not fully supported by all browsers.
 // what this function does is wait until the DOM (Document Object Module) 
 // is loaded and ready to be manipulated which is when we want to start using it.
 ready: function(fn){
  
  // check if we can use the addEventListener method, which is currently 
  // supported in Opera, Firefox, and other standard browsers.
  if(document.addEventListener){
  
   document.addEventListener("DOMContentLoaded", function(){
    // remove the event that we just added; which would be defined as the callee
    document.removeEventListener("DOMContentLoaded", arguments.callee, false);
	fn(); // call the function that was given to the ready function.
    // the DOM is loaded, if this event is fired so we can set isReady true.
    isReady = true;
   } , false);
   
   return;
	
  // the addEventListener method doesn't exist, it may be an Internet Explorer browser,
  // which has the attachEvent listener method.
  } else if(document.attachEvent) {
   
   // ie's way of checking for DOM's complete
   document.attachEvent("onreadystatechange", function(){
	if(document.readyState === "complete"){
	 // detach the event after we attached it and the DOM is complete.
     document.detachEvent("onreadystatechange", arguments.callee);
	 fn(); // call the function that was given to the ready function.
	 // the DOM is loaded, if this event is fired so we can set isReady true
	 isReady = true;
   };});
   
   return;
   
  };
  
  // fall-back if nothing else works...
  ty.events(window, "load", fn);
  
 },
 
 // this adds an event listener to either IE or one of the
 // better browsers; and then calls the function when the 
 // event listener is called by the visitor.
 events: function(obj, type, callBack, detach) {
  
  // check if they gave us an object or string, then return
  // the object from it; if it already is an object it returns itself,
  // but if it's a string it will try to return the object; if not...
  // then it will return false and won't do anything.
  obj = checkObjectTag(obj);
  if(obj==false){return false;};
  
  // this is if they actually want to add an event listener.
  if(obj != false && (detach == false || detach == null)){
   // if this exists, then that means we are running a standard
   // browser, and we are not running Internet Explorer.
   if(obj.addEventListener){
    obj.addEventListener(type, callBack, false);
    return true; // the event was added successfully.
   } else if(obj.attachEvent) {
    // we must include 'on' because it's an IE browser
    var r = obj.attachEvent("on"+type, callBack);
    return r; // the event was added successfully.
   } else { return false; };
  };
  
  // this is if they when they want to remove an already
  // added event listener that is no longer needed.
  if(obj != false && (detach == true)){
   // if this exists, then that means we are running a standard
   // browser; and not Internet Explorer
   if(obj.removeEventListener){
	obj.removeEventListener(type, callBack, false);
	return true; // event was removed successfully.
   } else if(obj.detachEvent) {
    var r = obj.detachEvent("on"+type, callBack);
	return r; // the event was successfully removed in IE.
   } else { return false; };
  };
  
 },
 
 // this function allows the use of cookies, which you can
 // either create a cookie, check if a cookie exists, or 
 // delete an existing cookie on the domain.
 cookie: function(name, value, options) {
 // acceptable options parameters:
 // expires, path, domain, secure
 if(typeof value != 'undefined') { // name and value given, set cookie
 
  var expires = '';
 
  options = options || {};
  if(value === null) { value = ''; options.expires = -1; }
   
  if(options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) { var date;
   if(typeof options.expires == 'number') {
    date = new Date();
    date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
     } else {
    date = options.expires;
   }
   expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
   }

  var path = options.path ? '; path=' + (options.path) : '';
  var domain = options.domain ? '; domain=' + (options.domain) : '';
  var secure = options.secure ? '; secure' : '';
  
  document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
  
  } else { var cookieValue = null;
   
   if(document.cookie && document.cookie != '') {
    var cookies = document.cookie.split(';');
     for(var i = 0; i < cookies.length; i++) {
      var cookie = (cookies[i]);
	  cookie = (cookie.trim());
       if(cookie.substring(0, name.length + 1) == (name + '=')) {
        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
        break;
       }
    }}
    
	return cookieValue;
    
  } // end of first-if block
 
 },
 
 loadXML: function(src){
  var xmlDoc; // the xml document inmplementation
  if(window.XMLHttpRequest){
   // this will only work on modern / standard browsers,
   // escpially internet explorer; which uses activex.
   xmlDoc = new window.XMLHttpRequest();
   xmlDoc.open("GET", src, false);
   xmlDoc.send("");
   return xmlDoc.responseXML;
  } else if(ActiveXObject("Microsoft.XMLDOM")){
   // this will only work within the internet explorer
   // realm; throughout activex suppported IE browsers.
   xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
   xmlDoc.async = false;
   xmlDoc.load(src);
   return xmlDoc;
  };
 },
 
 // the following will allow you to work with asynchronous javascript and 
 // script tag injections into remote servers allowing you to access data
 // on other servers where most options are blocked due to policy restrictions.
 ajast: function(src, fn){
  
  // create a new script element which will point towards a remote 
  // host which will load all the data for us; even ajax pointers.
  var script = document.createElement('script');
  script.type = 'text/javascript'; // js-pointer 
  script.src = src; // load the javascript file
 
  ty.events(script,"load",fn); // after it loads, fire the event.
  // Find the head of the document and inject the script reference
  var head = document.getElementsByTagName('head')[0];
  head.appendChild(script);
  return true;
  
 },
 
 
 jsonp: {
	 
   // the following variables are some services that already provide and support the JSONP 
   // or (JSON with "padding") method.  you can use sources that are not provided on this list.
   yahoo: "http://search.yahooapis.com/WebSearchService/V1/webSearch?appid=Yahoo&format=pdf&output=json",
   flickr: "http://www.flickr.com/services/feeds/photos_public.gne?format=json&tags=",
   
   request: function(src, callback){
	

   },
   
 },
 
 // the following commands are for AJAX interaction
 ajax: function(ajaxOptions) {
 
  // * the AJAX command takes the following object parameters:
  // @ type: - String: $_GET, $_POST; method type used.
  // @ url: - String: URL to the server-side file.
  // @ data: - String: Data sent to the server script.
  // @ callback: - Function: Callback function for success or failure
  // @ cont - Boolean: Call the callback function when the ready state
  // is at the right state, which means it has been sent and completed.
  // this function retrurns an 2D array, for if we succeeded or failed.
  // and the data sent back from the server.
  
  // example use: $.ajax({type: "GET", url: "", data: "", callback: fn});
  
  var xmlObject = null; 
  
  var success = new Boolean(false);
  var str_type = new String(ajaxOptions.type);
  var str_url = new String(ajaxOptions.url);
  var str_data = new String(ajaxOptions.data);
  var bool_cont = new Boolean(ajaxOptions.cont);
  var fn = ajaxOptions.callback;
  
  // if the type has not been set, the default will be GET method.
  if(str_type == "" || str_type == "undefined") str_type = "get";
  if(!bool_cont) bool_cont = false;
  
  // try creating the object for any standard browser (Firefox, Opera, Safari..etc)
  try{ xmlObject = new XMLHttpRequest(); } catch (e){
  // we cannot create for standard, it may be Internet Explorer
  try{ xmlObject = new ActiveXObject("Msxml2.XMLHTTP"); } 
  // if we cannot create for either, than it is an older  browser.
  catch(e) { xmlObject = new ActiveXObject("Microsoft.XMLHTTP"); }}
  
  // after trying to create the object, if it is still null; than
  // we cannot continue because the object has not been created.
  if(xmlObject != null){
   
   if(bool_cont == false) { xmlObject.onreadystatechange = fn; };
   if(bool_cont == true) { 
    xmlObject.onreadystatechange = function(e){
	 if(this.readyState == 4 && this.status == 200) {
	  fn(this.responseText);
	};};
   };
   
   xmlObject.open(str_type, (str_url + str_data), true);
   xmlObject.send(null);
   
  } else {
 
   // object could not be created
   return false;
   
  };
  
 }, // end of ajax function
  
 obj: {
  fx: {
   
   // this function allows you to toggle between two different states, which would
   // be two different functions that change what you would need to change.
   toggle: function(obj, callback1, callback2){
    
	obj = checkObjectTag(obj); // check if the object exists
    if(obj == false) { return false; }; // it doesn't exist.
	
	var exists = false; // does the toggle state exist already?
	// if we already have a toggle state on this function; then we
	// cannot add another toggle state unless we remove the other toggle
	// state function; because they would conflict against each other.
	if(toggleStates.length > 0){
	 for(var i=0;i<=(toggleStates.length-1);i++){
	  if(obj == toggleStates[i][2]){ return false; } else { exists = true; }
	 };
	} else {
	 exists = true;
	};
	
	// the toggle didn't exist; we can add the new toggle to the object.
	if(exists == true){ toggleStates.push(new Array(callback1, callback2, obj, false)); };
	
	// make sure that we have an existing object.
    if(obj != false){
	 ty.events(obj, "click", function(e){
	  
      var obj = null;
      // the following allows us to access the object from the mouse event 
      // that was triggered.  the following allows us to access the object
      // across different browsers including internet explorer and the safari bug.
      if(!e) var e = window.event;
      if(e.target) obj = e.target;
      else if (e.srcElement) obj = e.srcElement;
      if (obj.nodeType == 3) obj = obj.parentNode;
	  
      for(var n=0;n<=(toggleStates.length-1);n++){
       if(obj == toggleStates[n][2]){ // does the object match the toggle object?
		if(toggleStates[n][3] == false) toggleStates[n][0](e); // first toggle state
		if(toggleStates[n][3] == true) toggleStates[n][1](e); // second toggle state
		toggleStates[n][3] = !toggleStates[n][3]; // change what the current state is
	  };};
	  
	 }); // new function we are adding.
	}; // object exists
   
   },
   
   // this is one of the best multi-purpose animation functions.  animate allows you to 
   // animate many of one object's parameters simultaneously by sending it the parameters
   // you want with the values; and then carrying it out until it's finished.
   // @ obj ; the object you want to animate with.
   // @ arrParams ; the parameters / styles that you want to effect.
   // @ time ; how long you want the animation to take.
   currentParams: null, alreadyParams: null,
   animate: function(obj, arrParams, time, running, runtime){
	
    var done = new Boolean(false);
    // check if the object exists, and if it doesn't
	// then make sure we return false.
    obj = checkObjectTag(obj);
    if(obj == false){ return false; };
	
	var retData = function(curParam){
	 var str = new String(curParam);
	 var arrData = new Array();
	 // split the data into pieces so we can get the selector
	 // and the value by itself; this way we can set and get the
	 // values for the given style.
	 arrData = str.split(":");
	 return(new Array(arrData[0],arrData[1]));
	};
	
	var correctSyntax = new RegExp(/^\w+(-)?\w+:\w+$/);
     
	 // this is the first time we are running this function with this data
	 // so what we are doing is running this to see if they gave us invalid
	 // data before continuing or else we could set invalid properties.
	 if(running == false || running == null){
	  ty.obj.fx.alreadyParams = arrParams;
	  ty.obj.fx.currentParams = new Array();
	  runtime = 0; //we haven't looped at all yet.
	  for(var i=0;i<(ty.obj.fx.alreadyParams.length);i++){ 
	   var currentStyle = new String(ty.obj.fx.alreadyParams[i]);
	   currentStyle = currentStyle.replace(" ","");
	   var doesMatch = (correctSyntax.test(currentStyle));
	   // if the match didn't go through then we cannot continue 
	   // because we have invalid data in the array so we will 
	   // yell back to them an error.
	   if(doesMatch == false) { return false; }
	   var dat = (retData(currentStyle));
	   var currentData = (ty.obj.getStyle(obj.id, dat[0]))
	   ty.obj.fx.currentParams.push(new Array(dat[0],currentData));
	  }; // end of loop
	 }; // end of first-run
	 
	 // here we will go through each of the parameters and we will change
	 // them accordingly to the object we are using for this function.
	 for(var o=0;o<(ty.obj.fx.alreadyParams.length);o++){
      
	  var arrStyle = (new String(ty.obj.fx.alreadyParams[o]));
	  arrStyle = arrStyle.replace(" ","");
	  var arrDat = retData(arrStyle);
	  // this piece of information right here is what goes after
	  // the numerical values that is in curDat[1]; this will 
	  // be added at the end once we increment the values.
	  var str = (new String(arrDat[1]).replace(new RegExp(/[0-9]*/),""));
	  var curDat = (parseInt(ty.obj.fx.currentParams[o][1]));
	  var destValue = (parseInt(arrDat[1]));
	  
	  if(curDat != destValue){
	   
	   var camelCase = new RegExp(/^(\w)+(-)?(\w)+$/);
	   var nSelector = new String(ty.obj.fx.currentParams[o][0]);
	   var nCamel = nSelector.replace(/\-(.)/g, 
	   function(m, l){return l.toUpperCase()});
	   
	   // the increment and decrementing process of the 
	   // values which will become part of the animation.	   
	   if(curDat < destValue) {
		curDat = curDat + 1;
	   };
	   
	   if(curDat > destValue){
		curDat = curDat - 1;
	   };
	   
	   ty.obj.fx.currentParams[o][1] = curDat + str;
	   obj.style[nCamel] = new String(curDat+str);
	   
	  } else { done = true; };
	  
	 }; // end of for-loop
	 
	 if(done == false){
	  runtime += (parseInt(time));
      setTimeout("ty.obj.fx.animate('"+obj.id+"',"+null+
	  ",'"+time+"',"+true+","+runtime+");",time);
	 } else { return true; }
	
   }, // end of animate() function
   
   // the following function collapses the object using 1 of 2 methods; the first method
   // is to set it's height and overflow values and the 2nd way is to set both visibility 
   // and display properties.  either way works, but 1 may be needed more than the other.
   collapse: function(obj, method){
    
	////////    METHODS   ////////
	// Method 1.) $.gl.FX_HEIGHT(); uses height and overflow properties
	// Method 2.) $.gl.FX_DISPLAY(); uses visiblity and display properties
	obj = checkObjectTag(obj);
	
	if(obj != false){
	 
	  switch(method.toLowerCase()){
	   case ty.gl.FX_HEIGHT(): // first method
	    obj.style.display = "none";
		obj.style.visibility = "hidden";
	   case ty.gl.FX_DISPLAY(): // second method
	    obj.style.height = "0px";
		obj.style.overflow = "hidden";
	  };
	  
	 } else {
	  
	  // the object doesn't exist.
	  return false;
	 
	};
	
   },
   
   // the following function expands an object using 1 of 2 methods; it's the same as the 
   // object.effects.collapse function, but this will expand the object to be visibile 
   // and not hidden or collapsed as before.
   expand: function(obj, method){
    
	////////    METHODS   ////////
	// Method 1.) $.gl.FX_HEIGHT(); uses height and overflow properties
	// Method 2.) $.gl.FX_DISPLAY(); uses visiblity and display properties
	obj = checkObjectTag(obj);
	
	if(obj != false){
	 
	  switch(method.toLowerCase()){
	   case ty.gl.FX_HEIGHT(): // first method
	    obj.style.display = "block";
		obj.style.visibility = "visible";
		return true;
	   case ty.gl.FX_DISPLAY(): // second method
	    obj.style.height = "auto";
		obj.style.overflow = "hidden";
		return true;
	  };
	  
	 } else {
	  
	  // the object doesn't exist.
	  return false;
	 
	};
	
   },
   
   // this is another animation function which creates a slide effect either
   // downwards, or upwards enabling the content to be shown or hidden.  you can 
   // trigger how fast you want it to be shown.
   slide: function(obj, ease, type, sec, autoStart, currentHeight){
  
    // this function stores all the previous slides so it can 
    // keep track of the maximum height used in the slides.  
    
    obj = checkObjectTag(obj);
	if(obj == false){ return false; }
	
	if(obj != false){
	 
	 var maximumHeight = new Number(); // max height of this object
	 var op = new Number(); // the current operation
	 var found = new Number(0);
	
	 // only continue this part if we know there is already data we 
	 // can check for ... otherwise theres no point in checking.
     if(slidesArray.length != 0){
	 
	  // check if we already have the object and the height listed, 
	  // if we do then we'll use it so we don't have to re-catalog.
	  for(var i=0;i<=(slidesArray.length-1);i++){
	   if(obj == slidesArray[i][0]){
		maximumHeight = slidesArray[i][1];
		found = 1;
	  };};
	  
	  // we have not added this value to the array yet, which means
	  // they want to slide more than one object, so we need to add it.
	  if(found != 1){ 
	  
	   if(type == ty.gl.OPEN()) {
	    var previousHeight = (parseInt(obj.offsetHeight)); 
	    obj.style.height = "auto";
	   };
	  
	   maximumHeight = (parseInt(obj.offsetHeight));
	   slidesArray.push(new Array(obj,maximumHeight));
	  
	   if(type == ty.gl.OPEN()) { obj.style.height = previousHeight + "px"; }
	  
	  };
	  
	 } else {
	  
	  // if the current type is to open; then we want to make sure that
	  // we get the full maximum height; so what we do is change the height
	  // to auto and then record that height into maximumHeight, once we do 
	  // this we revert the object's height back to it's previous state.
	  if(type == ty.gl.OPEN()) {
	   var previousHeight = (parseInt(obj.offsetHeight)); 
	   obj.style.height = "auto";
	  };
	  
	  // this is the first item we are adding which obviously means
	  // there is nothing in our list to check for.  so we will add this
	  // item meaning next time their will be something to check for.
	  maximumHeight = (parseInt(obj.offsetHeight));
	  slidesArray.push(new Array(obj,maximumHeight));
	  
	  // revert the object's height back to it's previous state.
	  if(type == ty.gl.OPEN()) { obj.style.height = previousHeight + "px"; }
	  
	 };
	 
	 // this checks to see if the current height is already equivalent to the 
	 // current height with the same type.  if it is then don't move because
	 // we would just be replaying the same animation.
	 if(type == 0 && obj.offsetHeight == 0) return true;
	 if(type == 1 && obj.offsetHeight == maximumHeight) return true;
	 
	 // now that we have the maximum height we can continue with the sliding 
	 // process; even if we don't use it; we still check because this object
	 // may never been slidden before so we have to find the maximum height.
	 // @ running , @ currentHeight only used when recurvise is in-effect.
	 
	 if(isNaN(sec) || isNaN(type)) return false; // cannot continue with invalid data.
	 
	 // make sure we specify what operation we will
	 // be preforming on the height.
	 switch(type){
	  case 0: op = new Number(-1); 
	  currentHeight = maximumHeight; break;
	  case 1: op = new Number(1); 
	  currentHeight = 0; break;
	 };
	 
	 // the following settings need to be set in order to make the object
	 // animate and collapse or expand back to it's maximum height.
	 obj.style.display = "block"; obj.style.overflow = "hidden";
	 var myTween = null;
	 
	 if(type==0) myTween = (new Tween(obj.style,"height",ease,maximumHeight,0,sec,"px"));
	 if(type==1) myTween = (new Tween(obj.style,"height",ease,0,maximumHeight,sec,"px"));
	 if(autoStart == true) myTween.start();
	 return(myTween);
	 
	}; // end of checking for an existing object
	
   },
   
   // this function stops all current visual effects 
   // that are playing on any objects.
   stop: function() { animeStop = true; },
   
   // this allows you to fade in and fade an object out with the correct parameters
   // given.  this is an animation and requires the object, and optionally takes the type
   // and how fast you want to animate it.  the default type, and time it takes to animate
   // can be edited in the global variables if need-be.
   fade: function(obj, fadeFrom, fadeTo, msPer, callback, currentFade, running) {
   
    var operation = new Number(0); 
	// @ currentFade, @ running are both set with the setTimeout function and are 
	// not used in the actual running of the script unless the user specifies.
	obj = checkObjectTag(obj);
	
	if(obj != false){
	 
	 // one of the given numbers that we are going to use isn't a number....
	 if(isNaN(fadeFrom) || isNaN(fadeTo) || isNaN(msPer)) return false; 
	 
	 // if fadeFrom is equivalent to nothing or doesn't exist, then make sure
	 // we retrieve the value of the current opacity from the object, if we cannot
	 // for some reason retrieve it...then return false.
	 if((!fadeFrom || fadeFrom < -1 || fadeFrom > 100) && (running == false || !running)) { 
	  // retrieve alpha value from itself, but multiply by 100 because the value 
	  // given from this function returns in decimals of 0 to 1 and we need something
	  // from 0 to 100.
	  if(fadeFrom != 0) fadeFrom = (ty.obj.alpha(obj) * 100);
	 };
	 
	 if(fadeFrom > fadeTo) operation = new Number(-1); // do a negative operation
	 if(fadeFrom < fadeTo) operation = new Number(1); // do a positive operation
	 
	 // if we are not running then make sure to set the currentFade to the fadeFrom
	 // and then reset the animation mode and turn it back on so we can continue.
	 if(running == false || !running) { currentFade = fadeFrom; animeStop = false;};
	
	 // we have not reached the value specified so we must continue till we hit.
	 // also we need to make sure that they have no triggered the animateStop 
	 // variable which means they don't want to animate anything anymore. 
	 if(running == true){
	  if(fadeFrom > fadeTo) if(currentFade <= fadeTo) {
	   // make sure that the callback is not null; and then check if it's a function 
	   // before we go ahead an make a function call on it...
	   if(callback != null && (typeof callback.constructor == 'function')){callback();}
	  return true; };
	  if(fadeFrom < fadeTo) if(currentFade >= fadeTo) {
	   // make sure that the callback is not null; and then check if it's a function 
	   // before we go ahead an make a function call on it...
	   if(callback != null && (typeof callback.constructor == 'function')){callback();}
	  return true; };
	 };
	 
	 if(currentFade != fadeTo && animeStop == false) {
	 
	  currentFade = (currentFade + operation);
	  ty.obj.alpha(obj, currentFade);

	  setTimeout("ty.obj.fx.fade(\""+obj.id+"\","+fadeFrom+","+fadeTo+
	  ","+msPer+","+callback+","+currentFade+","+true+")", msPer);
	  
	 };
	 
	} else {
	 // object doesn't exist
	 return false;
	};
	
   }, // end of fade fx function
   
   // this function hides the given tags. this function can either close 
   // the first, last, and all tags all at once, or it can close a specific
   // object, or id given to the function provided by context.  tags is optional
   // if you are chosing to close a predefined method, or only want to close the
   // id / object if it is that tag.
   hide: function(context, tags, show) { var todo = new Number(-1);
    
	if(!show) show = 0; 
	
    // ex: $.obj.fx.hide($.gl.ALL(),"div"); // closes all tags
	if(typeof context != "object"){
     if(context.toLowerCase() == ty.gl.ALL()) todo = 0; // all type
	 if(context.toLowerCase() == ty.gl.FIRST()) todo = 1; // first type
	 if(context.toLowerCase() == ty.gl.LAST()) todo = 2; // last type
	}
	
	// after checking if we are running one of the pre-defined tags , and if we are not, 
	// then check if we can return false if the condition is true.
	if(todo == -1){if(!context || document.getElementById(context) == null) { return(false); }}
	
	// to-do is greater than 1, meaning we have a defined method they are
	// wanting to use, this would stay -1 if they didn't choose.
	if(todo > -1) {
		
	 // if the optional tags is not defined, then the default search
	 // will be kicked into order, because they haven't defined what,
	 // these refer to the ALL, FIRST, and LAST tags
	 if(!tags || tags == "") { tags = ty.gl.DEFAULT_SEARCH(); }
	 var mtags = document.getElementsByTagName(tags);
	 
	 for(var i=0;i<=(mtags.length-1);i++){
	  // the current tag we have selected.
	  var curtag = mtags[i];
	  if(todo == 1 && i == 0) checkShowHide(show, curtag);
	  if(todo == 2 && i == (mtags.length-1)) checkShowHide(show, curtag); 
	  if(todo == 0) checkShowHide(show, curtag);
	 }
	 
	} else {
	 
	 // to-do is not greater than 1, meaning that it is either an object, 
	 // or an ID tag, which we will convert into an object.
	 // if(typeof context == String) context = document.getElementById(context);
	 
	 // hide the object right away if the tag isn't defined, if the tag is defined,
	 // then only hide the ID/Object if the tag is the same as the object
	 if(!tags || tags == "") {
	  checkShowHide(context);
	 } else { // there is a tag
	  if(typeof context == "object") checkShowHide(show, context);
	  if(typeof context == "string") {
	    var tagObject = (document.getElementById(context));
		checkShowHide(show, tagObject);
	  };
	 }; // if not existent, or no tags
	 
	}; 
	
	return true;
	
   },
   
   show: function(context, tags) { 
    // re-routes to the hide function, but carries with
	// it the information to show the object instead.
    ty.obj.fx.hide(context, tags, 1);
   },
   
   // create a hover over and hover out effect by using this function, 
   // this allows you to create a toggle without using onmouseovers in xhtml.  
   // to create a hover effect you'll need to specify either 2 different
   // image paths, or 2 different class names; either will work.  
   // note: data1 is applied to the mouse out event, and data2 is applied
   // to the mouse over event.
   hover: function(obj, data1, data2) {
	
	obj = checkObjectTag(obj);
	var file = new Boolean(false);
    
	// this will help us identify if they gave us a file name, or
	// just a class that is available through a css file.
    var result = data1.indexOf("/");
	var result2 = data2.indexOf("/");
	
	if(obj != false){ 
	 
	 // following events are added if the result given was a file path
	 if(result > 0){
      ty.events(obj, "mouseout", function(e){ obj.src = data1; });
	  ty.events(obj, "mouseover", function(e){ obj.src = data2; });
	 };
	 
	 // following events are added if the result given was a classname
	 if(result == -1) {
	  ty.events(obj, "mouseout", function(e){ obj.className = data1; });
	  ty.events(obj, "mouseover", function(e){ obj.className = data2; });
     }; 
	 
	} else {
     // object / tag doesn't exist, so we can not apply any events
	 // which means we cannot apply the hover.
	 return false;
	};
	
   },
   
   // this part of the effects library allows you to easily / dynamically,
   // add a dragging functionality to an object by attaching events to it 
   // so you can drag it anywhere on the screen.  you can also detach the 
   // attached dragging if you do not have use for it anymore.
   drag: {
	 
	 // the dragger part of the drag library has nothing to do with any of the other
	 // object literal functions of drag, it is standalone and is used for putting
	 // draggers on elements; for example, a window is moved around by it's titlebar,
	 // so the window would be the handle root and the titlebar would be the dragger.
	 dragger: {
		 
      obj: null,

      init: function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper){
       
	   o.onmousedown = ty.obj.fx.drag.dragger.start;
	   o.hmode = bSwapHorzRef ? false : true;
	   o.vmode = bSwapVertRef ? false : true;
	   o.root = oRoot && oRoot != null ? oRoot : o;
	   
	   if(o.hmode  && isNaN(parseInt(o.root.style.left))) o.root.style.left   = "0px";
	   if(o.vmode  && isNaN(parseInt(o.root.style.top))) o.root.style.top    = "0px";
	   if(!o.hmode && isNaN(parseInt(o.root.style.right))) o.root.style.right  = "0px";
	   if(!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px";
	   
	   o.minX  = typeof minX != 'undefined' ? minX : null;
	   o.minY  = typeof minY != 'undefined' ? minY : null;
	   o.maxX  = typeof maxX != 'undefined' ? maxX : null;
	   o.maxY  = typeof maxY != 'undefined' ? maxY : null;
	   o.xMapper = fXMapper ? fXMapper : null;
	   o.yMapper = fYMapper ? fYMapper : null;
	   o.root.onDragStart = new Function();
	   o.root.onDragEnd = new Function();
	   o.root.onDrag = new Function();
	  
	  }, // end of initialize method

      start: function(e){
       
	   var o = ty.obj.fx.drag.dragger.obj = this;
       e = ty.obj.fx.drag.dragger.fixE(e);
       var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
       var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
       o.root.onDragStart(x, y);
	   o.lastMouseX  = e.clientX;
	   o.lastMouseY  = e.clientY;

       if(o.hmode) {
        if(o.minX != null)  o.minMouseX  = e.clientX - x + o.minX;
        if(o.maxX != null)  o.maxMouseX  = o.minMouseX + o.maxX - o.minX;
       } else {
        if(o.minX != null) o.maxMouseX = -o.minX + e.clientX + x;
        if(o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x;
       };

       if(o.vmode){
        if(o.minY != null)  o.minMouseY  = e.clientY - y + o.minY;
        if(o.maxY != null)  o.maxMouseY  = o.minMouseY + o.maxY - o.minY;
       } else {
        if(o.minY != null) o.maxMouseY = -o.minY + e.clientY + y;
        if(o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y;
	   };

       document.onmousemove = ty.obj.fx.drag.dragger.drag;
       document.onmouseup = ty.obj.fx.drag.dragger.end;
	   return false;
	   
     }, // end of start method

     drag: function(e){
      
	  e = ty.obj.fx.drag.dragger.fixE(e);
      var o = ty.obj.fx.drag.dragger.obj;

      var ey  = e.clientY;
      var ex  = e.clientX;
      var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
      var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
      var nx, ny;

      if(o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX);
      if(o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX);
      if(o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY);
      if(o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY);

      nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
      ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));
      if(o.xMapper) nx = o.xMapper(y)
      else if(o.yMapper) ny = o.yMapper(x)
    
      ty.obj.fx.drag.dragger.obj.root.style[o.hmode ? "left" : "right"] = nx + "px";
      ty.obj.fx.drag.dragger.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px";
      ty.obj.fx.drag.dragger.obj.lastMouseX  = ex;
      ty.obj.fx.drag.dragger.obj.lastMouseY  = ey;
      ty.obj.fx.drag.dragger.obj.root.onDrag(nx, ny);
      return false;
	  
     }, // end of drag method

     end: function(){
   
       document.onmousemove = null;
       document.onmouseup   = null;
       
	   var root = (ty.obj.fx.drag.dragger);
       root.obj.root.onDragEnd(parseInt(root.obj.root.style[root.obj.hmode ? "left" : "right"]), 
       parseInt(root.obj.root.style[root.obj.vmode ? "top" : "bottom"]));
       root.obj = null;
 
      }, // end of end method

      fixE: function(e){
       if(typeof e == 'undefined') e = window.event;
       if(typeof e.layerX == 'undefined') e.layerX = e.offsetX;
       if(typeof e.layerY == 'undefined') e.layerY = e.offsetY;
       return e;
      } // end of fix element method
		 
	 },
	 
	 detach: function(dragElement) {
	  
	  // check if the dragElement was an ID or an Object
	  // and return the Object we need to detach the dragging.
	  dragElement = checkObjectTag(dragElement);
	  
	  if(dragElement != false){
	   
	   ty.events(dragElement,"mousedown",ty.obj.fx.drag.dragBegin,true);
	   ty.events(document,"mousemove",ty.obj.fx.dragging,true);
	   ty.events(document,"mouseup",ty.obj.fx.drag.dragEnd,true);
	   
	   dragElement.dragBegin = null;
	   dragElement.drag = null;
	   dragElement.dragEnd = null;
	   
	   return true;
	   
	  } else {
	   // the object given didn't exist, so therefore 
	   // we cannot remove / detach the dragging method.
	   return false; 
	  };
	  
	 },
	 
	 // this is the function you call when you want to add a dragging
	 // method to an object.  all it requires is the object you want to
	 // be able to move.
	 attach: function(dragElement) {
	  
	  // check if the dragging element we will be using
	  // to drag with actually exists; or if the id exists.
	  dragElement = checkObjectTag(dragElement);
	  
	  if(dragElement != false){
	   
	   // when the mouse is down on the dragging element; we want to
	   // trigger an event to dragBegin to start dragging the object.
	   ty.events(dragElement,"mousedown",ty.obj.fx.drag.dragBegin);
	   
	   dragElement.dragBegin = new Function();
	   dragElement.drag = new Function();
	   dragElement.dragEnd = new Function();
	   
       // return true if everything successfully went through,
	   // and if the object we are using exists.
       return true;
	   
	  } else {
	   // the object they wanted to use for dragging
	   // didn't exist so we cannot drag it.
	   return false;  
	  };
	  
	 },
     
	 // this is the beginning of the drag, where we have just triggered
	 // a mouse down event and we are about to move the object somewhere.
	 dragBegin: function(e) {
	  
	  var dragElement = null;
	  // make the dragElement equivalent to the private dragElement, or
	  // and the equivalent of itself.
	  if(!e) var e = window.event;
      if(e.target) dragElement = e.target;
      else if(e.srcElement) dragElement = e.srcElement;
      if(dragElement.nodeType == 3) dragElement = obj.parentNode;
      
	  // make sure that we have defined left and top positions; if not we will redefine
	  // them to 0,0 on the screen.
	  if(isNaN(parseInt(dragElement.style.left))) { dragElement.style.left = '0px'; }
	  if(isNaN(parseInt(dragElement.style.top))) { dragElement.style.top = '0px'; }
	  
	  // retrieve only the numerical values from the left
	  // and top positions and remove the measurements.
	  var x = parseInt(dragElement.style.left);
	  var y = parseInt(dragElement.style.top);
	  
	  // if e equals e then keep e; but if it doesn't 
	  // equal e then make it equal to window.event, which
	  // is what Internet Explorer uses.
	  e = e ? e : window.event;
	  
	  // make the mousex and mousey positions the equivlance to
	  // the object's relative client x, and y.
	  dragElement.mouseX = e.clientX;
	  dragElement.mouseY = e.clientY;
      
	  // callback on the dragBegin to the dragElement
	  dragElement.dragBegin(dragElement, x, y);
      
	  // add event listeners to keep dragging until finally
	  // the release there mouse and we hit the drag end.
	  ty.events(dragElement,"mousemove",ty.obj.fx.drag.dragging);
	  ty.events(dragElement,"mouseup",ty.obj.fx.drag.dragEnd);
	  
	  return false;
	
	 },
	
	 dragging: function(e) {
		 
	  var dragElement = null;
	  // make the dragElement equivalent to the private dragElement, or
	  // and the equivalent of itself.
	  if(!e) var e = window.event;
      if(e.target) dragElement = e.target;
      else if(e.srcElement) dragElement = e.srcElement;
      if(dragElement.nodeType == 3) dragElement = obj.parentNode;
      
	  // retrieve only the numerical parts of the 
	  // x and y positions of the dragElement
	  var x = parseInt(dragElement.style.left);
	  var y = parseInt(dragElement.style.top);
      
	  // the following is the same as the dragBegin function;
	  // and will do the exact same thing, the reason we do this,
	  // is because we are now in a mousemove event which is triggered
	  // evertime the mouse is moved over the object.
	  
      e = e ? e : window.event;
	  dragElement.style.left = x + (e.clientX - dragElement.mouseX) + 'px';
 	  dragElement.style.top = y + (e.clientY - dragElement.mouseY) + 'px';
 
	  dragElement.mouseX = e.clientX;
	  dragElement.mouseY = e.clientY;
      dragElement.drag(dragElement, x, y);
	 
	  return false;
	
	 },
 
	 dragEnd: function(e) {
	  
	  var dragElement = null;
	  // make the dragElement equivalent to the private dragElement, or
	  // and the equivalent of itself.
	  if(!e) var e = window.event;
      if(e.target) dragElement = e.target;
      else if(e.srcElement) dragElement = e.srcElement;
      if(dragElement.nodeType == 3) dragElement = obj.parentNode;
 
	  var x = parseInt(dragElement.style.left);
	  var y = parseInt(dragElement.style.top);
      
	  // we are now done with the drag since they
	  // released their mouse so we will stop here.
      dragElement.dragEnd(dragElement, x, y);
	  
	  // remove all the events that allow for further
	  // movement until the events are triggered again.
      ty.events(dragElement,"mousemove",ty.obj.fx.drag.dragging,true);
	  ty.events(dragElement,"mouseup",ty.obj.fx.drag.dragEnd,true);
	  
	 }
 
   }, // end of dragging part of the library
   
  }, // end of effects for objects
  
  // this function allows you to change the opacity of an object that
  // was specified.  this function works on IE, Safari, Firefox, and Opera.
  // since it works on these standard browsers; it should hopefully work on
  // many others incase needed for a special reason.
  alpha: function(obj, value){
   
   // check to see if the object / tag exists
   obj = checkObjectTag(obj);
   if(obj == false) { return false; };
   
   if((obj != false) && (value)){
	
	// this part of the function initially sets the alpha for the
	// browser.  the methods below are commonly found and should work
	// for many browsers.
	
    var object = obj.style;
	object.opacity = (value / 100); 
	object.MozOpacity = (value / 100); 
	object.KhtmlOpacity = (value / 100);
	object.filter = "alpha(opacity=" + value + ")";
	return true; // we successfully set the alpha
	
   };
    
   if((obj != false) && (!value)){
	// this part of the function returns the value that is currently set for
	// the alpha / opacity.  if the value could not be found then the value 
	// is most likely to be 100% opaque due to it never being set before.  
	
    var object = obj.style, count = new Number();
	var eachOpacity = new Array(object.opacity, object.MozOpacity, 
	object.KhtmlOpacity, object.filter);
	var count = new Number(0);

	for(var i=0;i<=(eachOpacity.length-1);i++){
	 if(eachOpacity[i] == "" || eachOpacity[i] == null){ count++; 
	 } else { return(eachOpacity[i]); break; };
	}; 
	
    // if the count is equivalent to the amount of methods then keep continuing...
	// if the value is less than 0 or doesn't exist, or no value was specified, then
	// return 1 because the default opacity would be 100% opaque.
	if(count == eachOpacity.length && (value < 0 || !value || value == "")) return 1;
	
   };
   
  }, 
  
  // apply a CSS block of code to an object that is specified
  // to use this function you need to create an Object, and then
  // put in the attribute names with the specified values, then 
  // apply it to the this function with the object.
  css: function(obj, cssObject){
   
   // check to see if the cssObject is actually an object, if this isn't an object,
   // then there is no point in going any further because we cannot extract both the 
   // attributes and actual values for each of them.
   if(typeof cssObject == "object"){
	// check to see if the object / tag exists
	obj = checkObjectTag(obj);
	
	if(obj != false){ 
	 // run through each attribute in the cssObject
	 for(params in cssObject){
	  obj.style[params] = (cssObject[params]);
	 }; return true;
	} else {
	  // our given object wasn't an existing object that we
	  // could manipulate with the cssObject.
	 return false;
	};
   } else {
	// the cssObject wasn't an object
    return false;
   }; 
   
  },
  
  // this function get's the current style using the selector-cases in CSS,
  // and is a really important function for retrieving current css-styles that
  // are set on elements / objects.  the return value is whatever the style 
  // property style is set to.
  getStyle: function(id, styleProp){
   var x = document.getElementById(id);
    if(x.currentStyle) {
     var y = x.currentStyle[styleProp];
    } else if(window.getComputedStyle) {
     var y = document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp);
     return y;
   };
  },
  
  // this handy function allows you to return all the elements in an array with the
  // class name given; node and tag parameters are optional.  the node is just what 
  // object should we use to search through; the default is the DOM.  the tag parameter
  // is what tags should is search through; the default is all of them.
  getElementsByClass: function(searchClass, node, tag){
   
   var classElements = new Array();
   // optional parameters that we don't really have to use.
   if(node == null) { node = document; }
   if(tag == null){ tag = '*'; }
   
   var els = (node.getElementsByTagName(tag));
   var elsLen = (els.length);
   var pattern = new RegExp('(^|\\\\s)'+searchClass+'(\\\\s|$)');
   
   for(i=0,j=0;i<elsLen;i++){
    if(pattern.test(els[i].className)){
	 classElements[j] = els[i];
	 j++;
   }}
   
   return classElements;
   
  },
  
  // this function is to replace the current element with another 
  // element by using the replaceChild method. 
  replaceWith: function(obj, newElement){
   
   obj = checkObjectTag(obj);
   newElement = checkObjectTag(newElement);
   
   if(obj != false && newElement != false){
	
    if(typeof newElement.constructor.toString().indexOf("object") != -1){
	 // since the new Element is an object; we can now replace the old 
	 // object with the new one.
	 obj.parentNode.replaceChild(newElement, obj);
	 return true;
	  } else {
	 // the new Element that is going to replace the current element
	 // is not an object; so we cannot replace the current one.
	 return false;
	};
	
   } else {
    // make sure the replacement object exists;
	// before we go ahead and replace it.
	return false;
   };
   
  },
  
  // this function set's the properties of the current object we are
  // about to manipulate.  this is a multi-purpose function which returns
  // different information. please look below to see exactly what is returned.
  // 1.) $.obj.attr(obj); - Returns all the attributes of the object in an Object.
  // 2.) $.obj.attr(obj,"alt"); - Returns the value of the given attribute.
  // 3.) $.obj.attr(obj,"alt","image1"); - Sets the value of the given attribute.
  attr: function(obj, data, value){
   
   obj = checkObjectTag(obj);
   
   if(obj != false){ // object exists...
    
	if(data != "undefined" && data){
     // check if they just wanted to return the value of the attribute
     if(!value || value == "undefined") { return(obj[data]); };
	 // set the value if the value is equal to nothing or is greater than nothing
	 if(value == "" || value.length > 0) { obj[data] = value; return true; };
	} else {
	 // they did not enter data, so we will return all the attributes 
	 // of the object that was given to us.
	 var properties = new Object();
	 for(n in obj.style){ properties[n] = obj[n]; }
	 return properties;
	};
	
   } else {
	
	// whatever they gave us wasn't valid information
	return false; 
	
   };
   
  }, // end of attr
  
  // myX returns the true position of the currently given 
  // object from any browser inlcuding safari, opera, firefox,
  // flock, chrome, internet explorer, etc...
  myX: function findPosX(obj){ var curleft = 0;
   
   obj = checkObjectTag(obj); // check for tag / object
   
   if(obj != false){ // object exists...?
    // check if offsetParent exists...if so, then
	// create a continous loop to get the current x
    if(obj.offsetParent) while(1) {
     curleft += obj.offsetLeft;
      if(!obj.offsetParent) break;
       obj = obj.offsetParent;
	  // if we couldn't access the x position from the 
	  // offsetParent, then the other way around would be 
	  // to directly access the x position property.
      } else if(obj.x)
       curleft += obj.x;
    return curleft;
   } else { return false; }
   
  },
  
  // myY returns the true position of the currently given 
  // object from any browser inlcuding safari, opera, firefox,
  // flock, chrome, internet explorer, etc...
  myY: function findPosY(obj){ var curtop = 0;
   
   obj = checkObjectTag(obj); // check for tag / object
   
   if(obj != false){ // object exists...?
    // check if offsetParent exists...if so, then
	// create a continous loop to get the current y
    if(obj.offsetParent) while(1) {
     curtop += obj.offsetTop;
      if(!obj.offsetParent) break;
       obj = obj.offsetParent;
	  // if we couldn't access the y position from the 
	  // offsetParent, then the other way around would be 
	  // to directly access the y position property.
	  } else if(obj.y)
       curtop += obj.y;
    return curtop;
   } else { return false; }
   
  }

  
 }, // end of object
 
 
 // this part of the library directly affects mainly images and specific parts of an 
 // image including pre-loading, image manipulation, and other things.
 img: {
  
  // this function preloads an image for later-use
  preload: function(src){
   var _img = new Image(); // create the new image
   _img.src = src; // load the new image with the path
  },
  
  // this function checks if the given path image will be
  // a valid path that can be used.
  valid: function(src){
   // the following regular expression checks if the path given to an image is a valid
   // path that can be used.  this works either locally or while online.  below is the 
   // format it checks for: http://www.mysite.com/lib/images/image1.jpg (true)
   // http:/www.mysite.com/lib/images/image1.zip (false)
   var validPath = (new RegExp(/^(file|http|https):\/\/\S+\/\S+\.(gif|jpg|jpeg|png)$/i).test(src));
   return(validPath);
  },
  
 },
 
 filter: {
  
  inx : function(tagtype, index, dataObject, defaultSet){
   
   // get all the tags with the same tagtype given by
   // the person who is calling the function.
   var tags = document.getElementsByTagName(tagtype);
   
   if(defaultSet == null){ defaultSet = 0; };
   // if the number is a valid number, and is greater than -1 and is less than
   // how many elements exists in the document; then we can continue ...
   if(isNaN(index) == false && (index > -1) && (index <= (tags.length - 1))){
	
	// check every item in the dataObject Object...
	for(items in dataObject){
	 
	 // this is only for the cssObject which is required for the 
	 // ty.obj.css() function; and is only proccessed for case 1
	 // and if only the style exists and not the attribute.
	 var cssObj = new Object();
	 // add the new custom property to the cssObject.
	 cssObj[items] = (dataObject[items]);
	 
	 // if both attributes and style properties both have the same existing
	 // elements such as width, height, border, and other properties, then 
	 // we need to make sure that we select either one; which can be changed
	 // by setting the defaultSet to 0; for Styles, and 1 for Attributes.
	 // NOTE: the default setting for defaultSet is automatically 0 if not set.
	 if((tags[index][items] != null) && (tags[index].style[items] != null)){
		 
	  switch(defaultSet){
	   case 0: ty.obj.css(tags[index], cssObj); break; // CSS was selected.
	   case 1: ty.obj.attr(tags[index], items, dataObject[items]); break; // Attributes are selected
	  };
	 
	 // if we hit this else-if; this means only the attribute of the 
	 // given element from the object exists; so we will send all 
	 // the information provided to the ty.obj.attr() function.
	 } else if(tags[index][items] != null){

	  ty.obj.attr(tags[index], items, dataObject[items]);
	  
	 // if we hit this else-if; this means only the style of the given
	 // element from the object exists; so we will send them all 
	 // the information to the ty.obj.css() function
	 } else if(tags[index].style[items] != null){
	  
	  ty.obj.css(tags[index], cssObj);
	  
	 };
	 
	}; // end of for-in
	
	return true;
	
   } else {
	// the number given had something wrong with it.
	return false;  
   };
	   
  }, // end of the inx function()
  
  // the following function provides a way to build a list, array, or an object
  // of values and elements from a form easily without the hassle of getting them
  // individually.  this will return the information received, or will return nothing
  // if the information given was incorrect.
  forming: function(form, typeObject){
   
   // @ form = can either be the form ID or the form Name
   // @ typeObject = can either be an Array or Object
   
   form = checkObjectTag(form);
   var objArray = null;
   // make sure the form exists before going on, and if it exists
   // we can then continue on by getting the elements from the form.
   if(form != false){
    
	// give them the specified object which they want in return.
	if(typeObject == ty.gl.ARRAY()) objArray = new Array();
	if(typeObject == ty.gl.OBJECT()) objArray = new Object();
	// collect all the elements we have from the form
	// object given, and then add them to the specified object.
    var elem = form.elements;
	// loop through the elements.
    for(var i=0;(i<=elem.length-1);i++){switch(typeObject){
	 // this will return the Array object with only the values.
     case ty.gl.ARRAY(): objArray.push(elem[i].value); break;
	 case ty.gl.OBJECT(): 
	  // this gets the ID as a String.
	  var strID = new String(elem[i].id);
	  // this will return the object as an Object with the elements 
	  // names as the ID; and the value as the element value
	  objArray[strID] = (elem[i].value); 
	 break;
	};};
	
	return objArray;
	
   } else {
	 
	 // return false if the form document doesn't exist
	 return false;
	 
   };
   
  }, // end of forming(); function
  
 }, // end of the filter/ ty Library
 
 // this part of the library contains utilities that help retrieve information such as 
 // browser information, checking for functions, arrays, serializing an array or object,
 // and many other things.
 utils: {
  
  // this utility allows you to translate one language into another form of language; 
  // this util. is supported by google and all translations are made through google.
  translation: {
	  
   // the simple variable lets us know whether the translation
   // utility library is ready to be used; if not we cannot use anything.
   transReady: false, txt2trans: "", fnCallback: null,
   // this function initializes the translation mechanism; you need to 
   // initialize the the translation utility before using it or you 
   // won't be able to use it;  this is because it requires an external
   // javascript source that is loaded in through google.
   init: function(fn, f){
    // the path to the initialization gears javascript file.
    if(!f||f==null||f=="undefined") f = "http://www.google.com/jsapi";
    // create a new script element which will point towards a remote 
    // host which will load all the data for us; even ajax pointers.
    var script = document.createElement('script');
    script.type = 'text/javascript'; // js-pointer 
    script.src = src; // load the javascript file
    ty.events(script,"load",function(e){
     ty.utils.translation.transReady = true;
	 google.load("language", "1");
	}); // after it loads, fire the event.
    // Find the head of the document and inject the script reference
    var head = document.getElementsByTagName('head')[0];
    head.appendChild(script);

   }, // end of initialization
   
   // this is one the important functions of the translation library,
   // it converts a given language to another language; note: you must
   // know what language you are inputting to get whatever it is 
   // you want to get in the output.
   translate: function(txt, oldLang, newLang, fn){
    if(ty.utils.translation.transReady==true){
     ty.utils.translation.txt2trans = txt; // the text to translate
	 ty.utils.translation.fnCallback = fn; // the callback function
	 google.setOnLoadCallback(function(ready){
	  google.language.translate(ty.utils.translation.txt2trans,
	   "en","es",function(result){ // use the translation , and then 
	   // once it's called back; the result will be stored in the result
	   // parameter; and we will fetch it and send it to the main callback.
	   ty.utils.translation.fnCallback(result.translation);
	 });});
	};
   }, // end of translation
   
  },
	
  // this part of the library contains functions that affect either the 
  // browser, or help retrieve information about the browser, 
  // version, manipulate and other functions. 
  bwsr: {
   // retrieves and returns the current browser information.
   agent: function() { 
    
	var browser = new Object(); // returns information about the current browser
	
	// our browser checking list, this list contains all the browsers that were found to be the most
	// used, more can be added if you have the need to check for more than these browsers.
	var browser_list = new Array("Opera","StarOffice","WebTV","Beonex","Chimera","NetPositive",
	"Phoenix","Firefox","Safari","SkipStone","Internet Explorer","Netscape","Mozilla");
	var checking_list = new Array("opera","staroffice","webtv","beonex","chimera","netpositive",
	"phoenix","firefox","safari","skipstone","msie","netscape","mozilla/5.0");
	// the current browser agent in lowercase letters, this will be how we check for 
	// the current browser that the visitor is using by comparing it.
	var agent = new String(navigator.userAgent.toLowerCase());
	
	for(var i=0;i<=(checking_list.length-1);i++){
	 if(agent.indexOf(checking_list[i]) != -1) {
	  browser.browserName = (browser_list[i]); 
	  break;
	};};
	
	browser.browserVersion = (navigator.appVersion);
	browser.isCookies = (navigator.cookieEnabled);
	
	return browser;
	
   } // end of agent
  } // end of utils/browser
  
 }, // end of utils
 
 // this part of the library gives exclusive functions that handle arrays.
 arrays: {
  
  // returns a flatten version of an array, meaning that if there are any 
  // arrays inside this array; or multi-demensional arrays; it will convert
  // it into an inline array.
  flat: function(array){
   
   var newArray = new Array(); // the new array we will return to them.
   // run through the array and make sure that we check if there are 
   // arrays inside the array so we can recurisvely get the value of them.
   for(var i=0;i<(array.length);i++){
    if(ty.arrays.isArray(array[i]) == true){
     // recursively inject the data back into the same function, and
	 // return the values seperately, as we add them into the new one.
	 newArray.push(ty.arrays.flat(array[i]));
	} else {
	 // whatever was just checked was not an array so we
	 // can just add the value directly to the new one.
     newArray.push(array[i]);
	};
   };
   
   // return the new array...
   return(newArray);
   
  },
  
  // this function will go through a specified array, or object; and try 
  // to find any values that are equivalent to the given value.  the returned
  // value will be either the index value of the array; or the key to the value
  // from the given object.
  inArray: function(value, array, sensitive){
   
   if(sensitive == null){ sensitive = false; };
   if(typeof sensitive != "boolean") return false;
   
   if(ty.arrays.isArray(array) == true){
     
	 for(var i=0;i<=(array.length-1);i++){switch(sensitive){
      case true: 
	 
	  // if sensitive is set to true then they want to use case-
	  // insensitive.  so if the value and array values are both
	  // strings then we will convert them to lower-cases.
	  if(typeof value == "string" && typeof array[i] == "string") {
	   if(value.toLowerCase() == array[i].toLowerCase()){
	    return i; 
	  };};
	 
	  // if we reached this far; then that means case-insensitive
	  // didn't have any effect; so we now need to check for numericals
	  // and everything else that; even though it will return the same result.
	  if(value == array[i]) return i;
	 
	  break;
	  // if they are not using case-insensitive, then we don't care
	  // about the casing; so we will just check if they are the same
	  // and if it is; then we will return the array-index of the value.
	  case false: if(value == array[i]) return i; break;
	 };};
	
	// nothing worked or was found. return false
	return false; 
	
   } else if(typeof array.constructor.toString().indexOf("object") != -1){
    
	for(keys in array){switch(sensitive){
	 case true:
	  
	  // if sensitive is on; then we are going to use case-insensitive
	  // with the object.  if the value exists within the object somewhere,
	  // the value returned will be true; and if not; it will be false.
	  if(typeof array[keys] == "string" && typeof value == "string"){
	   if(value.toLowerCase() == array[keys].toLowerCase()){
	    return keys;
	  };};
	  
	  // nothing we case-insensitive; so now we are going to check
	  // for case-sensitive, numerical values, etc ...
	  if(value == array[keys]) return true;
	  
	 break;
	 // if they are using case-insensitive; then we don't care about
	 // casing; we just want to check the values inside the object.
	 case false: if(value == array[keys]) return true; break;
	};};
	
	// nothing worked or was found. return false
	return false;
	
   };
   
  },
  
  // this function provides a way to shuffle the items randomly throughout
  // the array using the Fisher-Yates shuffle algorithim.
  shuffle: function(object){
   for(var j, x, i = object.length; i; 
	j = parseInt(Math.random() * i), x = object[--i], 
    object[i] = object[j], object[j] = x);
   return object;
  },

  // this function checks 
  each: function(object, callback){
   
   // the object that was given was an array; so we can right away
   // just go through each element and give it back to the callback.
   if(ty.arrays.isArray(object) == true){
	// loop through the array and send each item to the function.
    for(var i=0;i<=(object.length-1);i++){ callback(object[i]); };
   // the object that was given was an object; so we need to use the 
   // keys to get the values and then we can send it to the callback.
   } else if(typeof object.constructor.toString().indexOf("object") != -1){
    for(params in object){ callback(object[params]); };
   };
   
  },
  
  // this function checks to see if the object, array (duh), or any other type
  // of given type could be an array by checking it's constructor.
  isArray: function(object) { 
   var ret = new String(object.constructor.toString());
   if(ret.indexOf("Array") == -1) { return false; } else { return true; }
  },
  
  // this function checks an array for the same values, and then 
  unique: function(object) {
   // define our variables
   var a = [], i, l = object.length;
   for(i=0;i<l;i++){ // loop through the object array
    // check a as a string, and if the current object item string
	// matches with the long string inside a, then don't add it, but if 
	//they don't match; then add it to the array cause we don't have it yet.
	if(a.indexOf(object[i])<0){a.push(object[i]);};
   };
   // return the array
   return a;
  },
  
  // this function serializes the object into a GET url; or what you
  // see after the page your currently on, which would be the variables.
  serialize: function(object) {
   
   var URL = new String();
   // find out what kind of type we are dealing with.
   if(typeof object == "object") var type = 0;
   if(typeof object == "array") var type = 1;
   
   switch(type) {
    case 0: // type given is an object
	 for(param in object){
	  var strParam = new String(param.toString());
	  var strValue = new String(object[param].toString());
      (URL.length ==0) ? URL = (strParam + "=" + strValue) 
	  : URL += ("&" + strParam + "=" + strValue);
	 };
	break;
   };
   
   // return the serialized URL;
   return URL;
   
  }, 
  
  // converts an object to an array object, by taking all the custom properties
  // or properties...and puts them into an array and returns the result.
  iterateObj: function(object) {
   
   var myArray = new Array();
   for(items in object){
    myArray.push(object[items]);
   }; return myArray;
   
  }, 
  
  // merges together the two different arrays; this function also takes
  // objects into account, but will convert all objects into arrays and
  // keep only the values; order of merging goes a to b.
  merge: function(a, b) {
   
   // check if what we recieved is already an array; if not 
   // convert the object to into an array so we can merge them.
   if(ty.arrays.isArray(a) == false) { a = ty.arrays.iterateObj(a); }
   if(ty.arrays.isArray(b) == false) { b = ty.arrays.iterateObj(b); }
   // merge all the values from b to the a array.
   for(var i=0;i<=(b.length-1);i++) a.push(b[i]);
   // return the merged array.
   return a;
   
  }
  
 }, // end of arrays
 
 // this part of the library contains functions that directly affect string 
 // values; and help make conversion, like MD5, or trimming things easier.  to
 // get a full listing of functions in the string part of ty Library goto the 
 // top of this page; which provides all the functions and there parameters.
 str: {
  
  // this quick-snippet will help remove 
  // any spaces witin the string.
  trim: function(str){ 
   return(new String(str).replace(/^\s+|\s+$/g, '')); 
  },
  
  // this function checks if the string isn't really a string, but whether
  // there is a date inside.  this will see if it has a valid date format, 
  // and make sure that it's a valid month, day, and the year.
  isDate: function(str){
  
   // our regular expression which helps remove anything we don't need
   var datePat = /^(\d{1,2})(\/|-)(\d{1,2})(\/|-)(\d{4})$/;
   var matchArray = this.match(datePat);
   if(matchArray == null) return false;

   // parse the data into seperate variables
   var day = matchArray[1];
   var month = matchArray[3];
   var year = matchArray[5];
 
   // checks if the month is a valid month
   if(month < 1 || month > 12){ return false; }
   // checks if the day is a valid day
   if(day < 1 || day > 31){ return false; }
 
   // these months do not have 31 days in their month.
   if((month==4||month==6||month==9||month==11)&&day==31){ return false; }
 
   // if the month is february, then make sure we check for a leap year, due to the extra
   // day that falls upon that month, and also make sure to check if the day is greater than 29
   // days or if it's 29 days and is not a leap year.
   if(month==2){ var isleap=(year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
   if (day > 29 || (day==29 && !isleap)){return false;}}

   return true; // we have reached true, because of no errors.
  
  },
  
  // this function will find if there are any wild character valus 
  // within a string and return a boolean depending on the result.
  containsWildChars: function(str){
  
   // wild characters that can be contained inside a string.
   var iChars = "!@#$%^&*()+=-[]\\\';,./{}|\":<>?~_";
   var found = new Boolean();
 
   for(var i = 0; i < str.length; i++) {
    if(iChars.indexOf(str.charAt(i)) != -1){
     found=true; break;
    }else{
     found=false;
   };}; return found;
  
  },
  
  // this function will find if there are any numerical values
  // within a string and return a boolean depending on the result.
  containsNumerics: function(str){
  
   // the numbers that can be found inside a string.
   var Numbers = "0123456789"; 
   var found = new Boolean();
 
   for (i = 0; i < 10; i++){ 
    var temp = Numbers.split("");
    var returnval = str.match(temp[i]);
     if(returnval==temp[i]){found=true; break;}else{found=false;}
   } return found;
  
  },
  
  // this function is an important function within the PHP library, and has been 
  // converted over to JavaScript so we can encode MD5 hashes; you can also use 
  // this function to encode an ISO-8859-1 string to a UTF-8.
  utf8_encode: function(string){

   string = (string+'').replace(/\r\n/g, "\n").replace(/\r/g, "\n");
   var utftext = "", start, end, stringl = 0;
   start = end = 0; stringl = string.length;
    
   for (var n = 0; n < stringl; n++) {
    var c1 = string.charCodeAt(n);
    var enc = null;

    if(c1<128){ end++;
    } else if((c1 > 127) && (c1 < 2048)){
     enc = String.fromCharCode((c1 >> 6) | 192) + 
	 String.fromCharCode((c1 & 63) | 128);
    } else {
     enc = String.fromCharCode((c1 >> 12) | 224) + 
	 String.fromCharCode(((c1 >> 6) & 63) | 128) +
	 String.fromCharCode((c1 & 63) | 128);
    };
    
    if(enc != null){
     if (end > start) { utftext += string.substring(start, end); }
      utftext += enc; start = end = n+1;
     };
    };

    if (end > start) { utftext += string.substring(start, string.length); };
    return utftext;
  
  }, // end of utf8_decode
  
  // this is also a function provided by PHP, this allows you to safely and easily
  // transport and decode a message in JavaScript that was encoded in PHP.  Tthis 
  // function is based off the MIME base64 algorithim.
  base64_decode: function(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 = ty.str.utf8_encode(dec);
   return dec;
 
  } // end of bas64_decode
  
 }, // end of strings for ty Library
 
 convert: {
  
  // this function converts RGB (red, green, blue) values into 
  // the 16-numeral based system hexadecimal, ex: #000000 or black
  RGBFromHEX: function(hexCode){
   var valuePoints = {A: 10, B: 11, C: 12, D: 13, E: 14, F: 15};
   var valueReturns = new Array(6); // returned values for hex codes.
   var r = new Number(), g = new Number(), b = new Number(); // rgb values
 
   // the type of the given hexCode must be only a string 
   // or we won't be able to do anything with it.
   if(((typeof hexCode).toString()) == "string"){
    
    // did they include the octothorpe? if so; get rid of it
    // because we really don't need it at all in this conversion. 
    hexCode = hexCode.replace("#",""); hexCode = hexCode.toUpperCase();
    // the given hexadecimal needs to be 6 characters
    // long; otherwise it's not a valid RGB color unless it's 
    // written short-hand; which this function doesn't support.
    if((hexCode.length == 6)) {
  
     for(var i = 0; i < (hexCode.length); i++){ valueReturns[i] = -1;
  
      for(values in valuePoints){
       if(hexCode.charAt(i) == values){
	   // the hexadecimals character at the given position was
	   // equivalent to values key name; so we will replace the 
	   // value of valueReturns[i] with the correct value.
       valueReturns[i] = valuePoints[values];
      };};
  
      // if valueReturns[i] wasn't filled with any, but the -1; then 
      // there is no matches between A through F.  so we will just return
      // the value that was given to the hexadecimal.
      if(valueReturns[i]==-1)valueReturns[i] = eval(hexCode.charAt(i));
  
     }; // end of main for-loop
  
    // find the values for each of the primary colors; red, green, and blue.
    // we do this by using the first value and multiplying by 16-bits; then
    // adding the second value to that so if we had FF; it would be:
    // ((15 * 16) + 15)) = which would be equivalent to FF and 255.
    r = ((valueReturns[0] * 16) + (valueReturns[1]));
    g = ((valueReturns[2] * 16) + (valueReturns[3]));
    b = ((valueReturns[4] * 16) + (valueReturns[5]));
    return(new Array(r,g,b));
  
    } else { return false };
   // we were given something else other then what we 
   // needed, so we cannot do anything but return false.
   } else { return false; };
 
  }, // end of RGBFromHEX
 
  // this function converts Hexadecimals; a 16-numeral based system 
  // into RGB values; ex: 0,0,0 would convert to #000000
  HEXFromRGB: function(red, green, blue){
 
   // checks if we have valid RGB colors, 
   // will return false if it's invalid.
   var isRGB = function(val){
   if(val>-1&&val<257){return(true);
   }else{return(false);}}
 
   // this is an important part of the main function because it checks
   // if the values match and if they do; we return the keys name as a
   // string; which will be part of the hexadecimal; if nothing was 
   // found then we just return the value itself.
   var convertRGB = function(rgb){  
    var valuePoints = {A: 10, B: 11, 
    C: 12, D: 13, E: 14, F: 15};
    for(var i=0;(i<rgb.toString().length);i++){
    for(values in valuePoints){
     if(rgb == valuePoints[values]){
      return(values.toString());
    };};};
    return(rgb);
   };

   if((isRGB(red)==true)&&(isRGB(green)==true)&&(isRGB(blue)==true)){
  
    // the following variables convert each part of the hexadecimal
    // from the R, G, B values we retrieved.  we use the values to 
    // check against A-F and 0-9.  once we find them we divide them
    // by A, C and E by 16 and we get the remainders for B, D, & F.
    var a = new String(convertRGB(Math.floor(red/16))),
    c = new String(convertRGB(Math.floor(green/16))),
    e = new String(convertRGB(Math.floor(blue/16))),
    b = new String(convertRGB(red%16)),
    d = new String(convertRGB(green%16)),
    f = new String(convertRGB(blue%16));
    // return the concatenated version of what we just stored
    // into each variable.  this is now a string and no longer
    // numerical values.
    return(a+b+c+d+e+f);
  
   } else { return false; };
 
  } // end of HEXFromRGB
 
 }, // end of conversions library
 
 // this part of the library contains no external requirements; these are widgets
 // which allow you to get data from users in a more friendly Web 2.0 UI. 
 widgets: {
  
  // to use ty Widgets with ty Library, you need
  // to "use" them by including them into HTML.
  use: function(id, widgetName, params){
   
   widgetName = (new String(widgetName).toLowerCase());
   params.style = (new String(params.style).toLowerCase());
   // if no style is defined; then the default style will be used; which
   // always points back to the regular style for each type of widget.
   if(params.style==""||params.style==null||
   params.style=="undefined") params.style="regular";
   var widObj = (ty.o(id)); // convert ID to object
   
   if(widObj!=false){
    switch(widgetName){
     case "button": // widget Button
	  switch(new String(params.type).toLowerCase()){
	   case "simple": // simple button (DEFAULT)
        // the code below is global for each widget and each widget uses them for
        // a hover effect; which are defined by overStyle and the outStyle.
		if(params.noMouseOvers==null||params.noMouseOvers=="undefined") params.noMouseOvers=false;
        if(params.noMouseOvers==false) widObj.className = params.style; // use the new css style (for instance-effect)
        widObj.outStyle = params.style; // the mouse out style that will be used
        widObj.overStyle = params.style+"Over"; // mouse over style that will be used
		if(params.noMouseOvers==false){ // if this is false; we can use mouseovers.
         ty.events(widObj,"mouseover",function(e){this.className=this.overStyle;});
         ty.events(widObj,"mouseout",function(e){this.className=this.outStyle;});
		}; // we can only add mouse over events if this conditional statement is true
	   break; 
	   case "dropdown": // drop down menu
	    
		// this span will be the title; which all the drop down 
		// menu items will be nested under; to access them this
		// the main title drop down must be clicked.
		var ddButton = (widObj.getElementsByTagName("button")[0]);
		var ddMenu = (widObj.getElementsByTagName("h1")); 
		var nArrow = (document.createElement("img"));
		widObj.className = params.style+"DDMenu"; // this is for the main div-tag; which will
		// allow us to affect tags within the div element ; such as the list and the button.
		nArrow.src = "lib/img/buttons/"+params.style+"Arrow.png";
        ddButton.className = params.style; // use the new css style (for instance-effect)
        ddButton.outStyle = params.style; // the mouse out style that will be used
        ddButton.overStyle = params.style+"Over"; // mouse over style that will be used
        ty.events(ddButton,"mouseover",function(e){this.className=this.overStyle;});
        ty.events(ddButton,"mouseout",function(e){this.className=this.outStyle;});
		ddButton.style.width = (parseInt(ddButton.offsetWidth)+8)+"px";
		ddButton.style.cursor = "pointer"; // make it look-like a button
		ddButton.style.textAlign = "left"; // align left
		ddButton.myMenu = ddMenu; // the submenu
		ddButton.myMenuShowing = false; // is it showing
		widObj.appendChild(nArrow);
		
		ty.obj.fx.toggle(ddButton,
		function(e){
		 var bn = null;	
		 bn = (ty.returnElement(e));	
		 lastButtonWidget = bn; // the last button that was clicked
		 for(var dd=0;dd<(bn.myMenu.length);dd++){
		  bn.myMenu[dd].style.visibility = "visible";
		  bn.myMenu[dd].style.display = "block";
		  bn.myMenuShowing = true;
		 };
		}, // toggle state 1
		function(e){
		 var bn = null;	
		 bn = (ty.returnElement(e));	
		 lastButtonWidget = bn; // the last button that was clicked
		 for(var dd=0;dd<(bn.myMenu.length);dd++){
		  bn.myMenu[dd].style.visibility = "hidden";
		  bn.myMenu[dd].style.display = "none";
		  bn.myMenuShowing = false;
		 }; // toggle state 2
		});
		
		ty.events(document,"click",function(e){
         
		 var bn = null;	 // check if the clicked object was a button
		 bn = (ty.returnElement(e));	
		 if(lastButtonWidget!=null){
		 if(bn!=lastButtonWidget){ 
		  if(lastButtonWidget.myMenuShowing == true){
		   lastButtonWidget.myMenuShowing = false;
		   if(lastButtonWidget.dispatchEvent) { 
		    // the following dispatchment is for standard browsers
			// that support the dispatchEvent method; which does not
			// include internet explorer; because it uses fireEvent.
            var evt = document.createEvent("MouseEvents");
            evt.initMouseEvent("click",true,true,window,
		    0,0,0,0,0,false,false,false,false,0,null);
		    lastButtonWidget.dispatchEvent(evt);
		   } else if(lastButtonWidget.fireEvent) {
			// support for fireEvent for Internet Explorer Browser
		    lastButtonWidget.fireEvent("onclick");
		   };
		 };};}
		 
		},false);
		
		var widthButton = (ddButton.offsetWidth);
		var heightButton = (ddButton.offsetHeight);
		var heightArrow = (nArrow.offsetHeight);
		nArrow.style.position = "absolute";
		nArrow.style.left = (ty.obj.myX(ddButton)+widthButton-12)+"px";
		nArrow.style.top = (ty.obj.myY(ddButton)+
		(heightButton/2))-(heightArrow/2)+"px";
		
		for(var i=0;i<(ddMenu.length);i++){
		 // this part is to allow us to customize the dropdown menu items, by
		 // changing each of their widths to the size of the button, and making
		 // sure they act like a button.  we also need to make sure that they
		 // have their hover effects, which are also added at this point.
		 ddMenu[i].style.width = (parseInt(ddButton.offsetWidth)+"px");
		 ddMenu[i].className = params.style+"OutMenu";
		 ddMenu[i].styleOver = params.style+"OverMenu";
		 ddMenu[i].styleOut = params.style+"OutMenu";
		 ddMenu[i].style.cursor = "pointer";
		 
		 ddMenu[i].onmousedown = function(e){return false;};
		 ddMenu[i].onselectstart = function(e){return false;};
		 ty.events(ddMenu[i],"mouseover",function(e){this.className=this.styleOver;});
		 ty.events(ddMenu[i],"mouseout",function(e){this.className=this.styleOut;});
		 
		};
		
	   break;
	  }; // check all the existing button-types...
	 break; // end of widget button
	 case "inlineedit":
	  
	  widObj.style.cursor = "pointer";
	  widObj.myStyle = params.style; // make sure we know what style
	  widObj.editingMode = false; // we are currently not in editing mode
	  // check if they want the hovering over the inline edit box,
	  // if they don't then we will make sure there is no hovering.
	  if((params.hovering!=null||params.hovering!="undefined")&&(params.hovering==true)){
	   ty.events(widObj,"mouseout",function(e){
		// change class back to normal.
	    this.className = ""; 
	   }); // end of mouse out
	   ty.events(widObj,"mouseover",function(e){
		// change class to the mouseover state
		this.className = this.myStyle+"Editing";
	   }); // end of mouse over
	  }; // end of hovering
	  
	  ty.events(widObj,"click",function(e){
	   
	   var height = this.offsetHeight; // the height of the object
	   var width = this.offsetWidth; // the width of the object
	   var curObj = null; // the object being used throughout.
	   curObj = this; // default, the object equals this.
	   curObj = ty.returnElement(e); // returns the object
	   
	   // if the height and width properties are undefined or null, then we will
	   // try to access the data through the mouse event click's target, but first
	   // we must make sure that we have the right element for different browsers.
	   if(height=="undefined"||height==null||width==null||width=="undefined"){
		// these conditional statements check to see whether or not
		// the target exists; if not it will move to the next state.
        
		width = curObj.offsetWidth; // apply the new width 
		height = curObj.offsetHeight; // apply the new height
	   };
	   
	   var txtBox = (document.createElement("input"));
	   txtBox.className = curObj.myStyle+"Input";
	   txtBox.style.position = "absolute";
	   txtBox.style.height = height+"px";
	   txtBox.style.width = width+"px";
	   txtBox.value = curObj.innerHTML;
	   txtBox.style.left = (ty.obj.myX(curObj))+"px";
	   txtBox.style.top = (ty.obj.myY(curObj))+"px";
	   document.relatedInlineBox = curObj;
	   document.relatedTextBox = txtBox;
	   document.body.appendChild(txtBox);
	   
	   // set the focus to the textbox
	   if(params.setFocus==true) txtBox.focus();
	   // select everything in textbox
	   if(params.autoSelect==true) txtBox.select(); 
	  
	   ty.events(txtBox,"keyup",function(e){
		var curObj = (ty.returnElement(e));
	    document.relatedInlineBox.innerHTML = curObj.value;
	   });
	   
	  }); // end of the click mouseEvent
	  
	  ty.events(document,"click",function(e){
       var curObj = null; // check if the relatedObject is itself.
	   curObj = (ty.returnElement(e));
	   if((curObj!=document.relatedTextBox)&&(curObj!=document.relatedInlineBox)) { 
	    // the objects were not the same if this conditional
		// statement succeeds, if so; then we can delete the txtbox.
		if(document.relatedTextBox) document.body.removeChild(document.relatedTextBox);
	   }; 
	  });
	  
	 break; // end of inline edit box
	 case "tabcontainer":
	  
	  // get all the tabs; which we will then seperate
	  var tabs = (widObj.getElementsByTagName("div"));
	  var generated = (String.fromCharCode(97+Math.round(Math.random()*25)));
	  // if there is no value for the tab to open as default; then the default will
	  // be 0; if the tabOpened value is a larger value than the number of tabs that
	  // are provided for the tab container; then the value will also be set back to 0.
	  if((params.tabOpened==null||params.tabOpened=="undefined")||
	  (params.tabOpened > (tabs.length-1))) params.tabOpened = 0;
	  if(params.style==null||params.style=="undefined") params.style = "regular";
	  for(var i=0;i<(tabs.length);i++){
	   var nButton = (document.createElement("button"));
	   nButton.innerHTML = tabs[i].title; // set the value to the title
	   nButton.id = "tabs"+generated+i; // give the button a unique-ID
	   ty.widgets.use(nButton,"Button",{type:"simple", noMouseOvers: true}); // generate button
	   widObj.insertBefore(nButton,tabs[0]); // insert before first tab
	   if(i==params.tabOpened) { nButton.className = params.style+"lyButton"; }
	   else { nButton.className = params.style; };
	   nButton.theWidObj = widObj; // make sure the button knows the widget
	   nButton.tabCollection = tabs; // the tabs collection needed to be used.
	   nButton.selButton = params.style+"lyButton"; // the selected style.
	   nButton.unselButton = params.style; // the unselected style
	   nButton.currentSelection = false; // default selection
	   
	   nButton.unselButtons = function(myID){
		var getButtons = ((this.theWidObj).getElementsByTagName("button"));
		for(var i=0;i<(getButtons.length);i++){
		 if(getButtons[i].id!=myID){
		  getButtons[i].className = this.unselButton;
		  getButtons[i].currentSelection = false; // not current selection
		  getButtons[i].tabCollection[i].style.visibility = "hidden";
		  getButtons[i].tabCollection[i].style.display = "none";
		 } else {
		  getButtons[i].tabCollection[i].style.visibility = "visible";
		  getButtons[i].tabCollection[i].style.display = "block";
		 };
	   };}; // end of unselecting buttons fn
	   
	   ty.events(nButton,"click",function(e){
	    var myObject = (ty.returnElement(e));
	    myObject.className = myObject.selButton;
		myObject.currentSelection = true; // current selection
		myObject.unselButtons(myObject.id); // unselect other buttons
	   }); // end of click event for button
	   
	   ty.events(nButton,"mouseover",function(e){
	    var currentObject = (ty.returnElement(e));
		if(currentObject.currentSelection==true) 
		currentObject.className = currentObject.selButton+"Over";
		if(currentObject.currentSelection==false) 
		currentObject.className = currentObject.unselButton+"Over";
	   }); // end of mouseover for the button
	   
	   ty.events(nButton,"mouseout",function(e){
		var currentObject = (ty.returnElement(e));
		if(currentObject.currentSelection==true) 
		currentObject.className = currentObject.selButton;
		if(currentObject.currentSelection==false) 
		currentObject.className = currentObject.unselButton;						 
	   }); // end of mouseout for the button
	   
	   if(i==params.tabOpened) nButton.currentSelection = true;
	   if(i!=params.tabOpened){ // only show this tab and no others.
	   tabs[i].style.visibility = "hidden";
	   tabs[i].style.display = "none";
	   }}; // end of tabs loop
	  
	 break; // end of tabcontainer widget
	 case "dialog":
	  
	  if(params.dialog!=null&&params.dialog!="undefined"&&(ty.o(params.dialog)!=false)){
	   params.style = (new String(params.style).toLowerCase()); // lowercase
	   if(params.style==null||params.style=="undefined") params.syle = "regular";
	   
	   var dialogBox = (ty.o(params.dialog)); // the dialog box object.
	   widObj.className = params.style; // widget-object change class style.
	   widObj.outStyle = params.style; // the out-style for the mouseout event
	   widObj.overStyle = params.style+"Over"; // the over-style for the mouseover event
	   widObj.displayOb = (dialogBox); // make sure we have a reference to the dialog
	   dialogBox.style.visibility = "hidden"; // hide the dialog box
	   dialogBox.style.display = "none"; // turn off the display
	   ty.events(widObj,"mouseover",function(e){
	    var currentObject = (ty.returnElement(e));
	    currentObject.className = currentObject.overStyle;
	   }); // end of the mouseover event
	   ty.events(widObj,"mouseout",function(e){
        var currentObject = (ty.returnElement(e));
	    currentObject.className = currentObject.outStyle;
	   }); // end of the mouseout event
	   
	   ty.events(widObj,"click",function(e){						 
	   
        var currentObject = (ty.returnElement(e));
	    var dialog = (currentObject.displayOb);
		var containers = (dialog.getElementsByTagName("div"));
		
		if(widObj.isSetup == true){ // everything is already setup for the dialog box 
		 // so we do not have to go through all the code below; we can just open it.
		 widObj.myBackground.style.visibility = "visible";
		 widObj.myBackground.style.display = "block";
		 dialog.style.visibility = "visible";
		 dialog.style.display = "block";
		};
		
		if(containers.length == 2 && (widObj.isSetup==null||widObj.isSetup=="undefined")) { 
		 // there must be 2 parent div tags only too continue; the first div tag will be used
		 // for the title bar which will hold the exit button and the title; the second div tag
		 // will be used for the main information / description.  you can nest div's inside the 
		 // parent div's but you cannot use more than 2 parent divs or your dialog will not work.
		 var background = (document.createElement("div")); // create the bg
		 var btnClose = (document.createElement("img")); // the close button
		 dialog.style.visibility = "visible"; dialog.style.display = "block";
		 ty.obj.alpha(background, 75); // change opacity.
		 background.className = "dialogBackground"; // the background style
		 containers[0].className = ((currentObject.outStyle)+"Bar");
		 containers[1].className = ((currentObject.outStyle)+"Desc");
		 dialog.className = ((currentObject.outStyle)+"Dialog");
         document.body.appendChild(background);
		 background.appendChild(dialog);
		 
		 btnClose.src = "lib/img/feedback/"+(currentObject.outStyle)+"Close.png";
		 btnClose.style.position = "absolute"; // make sure that we give it an absolute positioning
		 containers[0].appendChild(btnClose); // add this exit button to the titlebar div container
		 var div_width = (containers[0].offsetWidth); var div_height = (containers[0].offsetHeight);
		 var img_width = (btnClose.offsetWidth); var img_height = (btnClose.offsetHeight);
		 btnClose.style.top = ((div_height/2)-(img_height/2)-1)+"px";
		 btnClose.style.left = (div_width-img_width-4)+"px";
		 
		 btnClose.referBackground = background;
		 btnClose.referDialog = dialog;
		 
		 ty.events(btnClose,"click",function(e){							 
		  var currentObject = (ty.returnElement(e)); 
		  currentObject.referBackground.style.visibility = "hidden";
		  currentObject.referBackground.style.display = "none";
		  currentObject.referDialog.style.visibility = "hidden";
		  currentObject.referDialog.style.display = "none";
		 });
		 
		 var myPositionX = parseInt(ty.obj.myX(dialog));
		 var myPositionY = parseInt(ty.obj.myY(dialog));
		 var myObjHeight = parseInt(dialog.offsetHeight);
		 var myObjWidth = parseInt(dialog.offsetWidth);
		 var screenX = parseInt(window.screen.availWidth);
		 var screenY = parseInt(window.screen.availHeight);
		 
		 dialog.style.position = "absolute";
		 dialog.style.left = ((screenX/2)-(myObjWidth/2))+"px";
		 dialog.style.top = ((screenY/2)-(myObjHeight))+"px";
		 containers[0].onselectstart = function(e){return false;};
		 containers[0].onmousedown = function(e){return false;};
		 ty.obj.fx.drag.dragger.init(containers[0],dialog);
		 
		 // setup is complete; we don't need to create another background.
		 // we also need to make sure we keep a reference to the background.
		 // also make sure that we have a reference to the close button.
		 widObj.myBackground = background;
		 widObj.myCloseButton = btnClose;
		 widObj.isSetup = true;
		 
		};
		
	   }); // end of click-mouse event
	  }; // we can only continue if the dialog exists.
	  
	 break; // end of dialog
	 case "titlepane":
	  
	  params.style = (new String(params.style).toLowerCase()); // make style lowercase
	  if(params.style==null||params.style=="undefined") params.style = "regular";
	  if(params.animate==null||params.animate=="undefined") params.animate = true;
	  // to use the title pane there are 2 XHTML parent node elements required,
	  // that are children of the div parent  (which is the widget).  you need
	  // to use an h1 tag for the titlebar; and a div tag element for content.
	  var title = (widObj.getElementsByTagName("h1")); // the titlebar element
	  var content = (widObj.getElementsByTagName("div")); // the content element
	  
	  if((title.length==1)&&(content.length==1)){
	   
	   var titleBar = (title[0]); // the first h1 tag encountered.
	   widObj.className = (params.style)+"Pane"; // customized style widget
	   titleBar.className = (params.style)+"PaneBar"; // customized style
	   titleBar.onselectstart = function(e){return false;};
	   titleBar.onmousedown = function(e){return false;};
	   
	   var title_width = (titleBar.offsetWidth); // the width of the titlebar
	   var title_height = (titleBar.offsetHeight); // the height of the titlebar
	   var title_yPos = (ty.obj.myY(title)); // get the y position of the titlebar
	   // the following code is for creating the pane arrow. this will allow us
	   // to tell what state we are in whether we can tell by hand or not ...
	   var arrow = (document.createElement("img")); // create the img element
	   arrow.src = ("lib/img/feedback/"+(params.style)+"ArrowD.png"); // source
	   arrow.style.position = "absolute"; // posiiton absolute so we can position
	   var arrow_width = (arrow.offsetWidth); // get the width of the arrow size
	   var arrow_height = (arrow.offsetHeight); // get the height of the arrow size
	   arrow.style.left = (title_width - arrow_width - 10) + "px"; // position right
	   arrow.style.top = (title_yPos) + (title_height+arrow_height) + "px";
	   titleBar.appendChild(arrow); // append the child to the titlebar
	   widObj.myArrow = arrow; // the arrow for the title pane widget
	   titleBar.myArrow = arrow; // the arrow for the title pane widget
	   titleBar.myContent = content[0]; // the content div that we have
	   titleBar.maxHeight = (content[0].offsetHeight); // maximum height
	   titleBar.animation = params.animate; // should we animate?
	   arrow.myStyle = (params.style); // style we are currently using
	   
	   ty.obj.fx.toggle(titleBar, 
	   function(e){ // toggle state #1  ; this occurs first
	    var currentObject = (ty.returnElement(e)); // trigger object
		currentObject.myArrow.src = ("lib/img/feedback/"+
	    (currentObject.myArrow.myStyle)+"ArrowN.png");
		if(currentObject.animation == true){ // animation will be used
		 ty.obj.fx.slide(currentObject.myContent, 
		 Tween.strongEaseOut, ty.gl.CLOSE(), .5, true);
		} else { // no animation is used.
 		 currentObject.myContent.style.visibility = "hidden";
		 currentObject.myContent.style.display = "none";
		};
	   }, 
	   function(e){ // toggle state #2 ; this occurs last
	    var currentObject = (ty.returnElement(e)); // trigger object
		currentObject.myArrow.src = ("lib/img/feedback/"+
	    (currentObject.myArrow.myStyle)+"ArrowD.png");
		if(currentObject.animation == true){ // animation will be used
         ty.obj.fx.slide(currentObject.myContent, 
		 Tween.strongEaseOut, ty.gl.OPEN(), .5, true);
		} else { // no animation is used.
 		 currentObject.myContent.style.visibility = "visible";
		 currentObject.myContent.style.display = "block";
		};
	   });
	   
	  }; // to check if there is only 1 of each h1 and div elements
	  
	 break; // end of title pane
    }; // end of widgets
   }; // object exists
   
  }, // end of use widget
  
  destroy: function(){
	  
  }, // end of destroy widget
  
 }, // end of widgets library
 
 // ty Library also includes support for Gears; a newly open-source project 
 // that supports more powerful web applications, by adding new features to 
 // web browsers that allow for local servers, databases, and a workerpool.
 gears: {
  
  // this is the core function that is required to initialize gears; before running
  // any other function within the gears throughout ty Library. call this function
  // if you are going to use any functions within the gears ty Library.
  // @ fn : Function - the callback ; this is what will be called upon after the 
  // google gears initialization has finished loading.
  // @ [initGears] : String - alternate path to gears initialization file.
  init: function(fn, initGears){
   
   // the path to the initialization gears javascript file.
   if(!initGears||initGears==null||initGears=="undefined") 
   initGears = "http://code.google.com/apis/gears/gears_init.js";
   ty.ajast(initGears, fn); // end of anyn.success function
   
  }, // end of initializing
  
  // this gears function checks to see if we have googles gears installed; 
  // if it's not installed ; nothing will happen; this function will be 
  // checked everytime you use a google gears function; and has optional
  // parameters for visitors to go download gears and more.
  installed: function(options){
   if(!window.google||!google.gears) {
    // google gears wasn't installed on this computer; so we cannot go
	// any further; so we will throw an error; and make sure if they want
	// to goto the installation page ; that they will be taken there.
	if(options.install==null||options.install=="undefined") options.install = false;
	if(options.message==null||options.message=="undefined") options.message = "Download Google Gears";
	if(options.url==null||options.url=="undefined") options.url = "";
    if(options.install == true){
     var installURL = "http://gears.google.com/?action=install&message=";
	 location.href = installURL+options.message+"&return="+options.url;
	 return false;
	};
	// if they didn't want to go to the google gears installation page then just 
	// return false, because we cannot continue doing anything else with gears
	return false;
   } else { // google gears is installed.
	return true;  
   };
  },
  
  // the geolocation function provided by gears allows us to get a highly 
  // "accurate" position of where the visitor lives using GPS and WiFi.
  // @ callBack: this is asking for a callback function to send the geo
  // location data back to; amke sure that you at least 1 parameter avail
  // ble so it can be stored within the arguments.
  geolocate: function(callBack, installOptions){
	  
    if(installOptions==null||installOptions=="undefined") 
	installOptions = {}; // create a blank object for installed function
	if(ty.gears.installed(installOptions)==true){
	 // check if google gears is currently installed.
	 // create the geolocation gears object ; which will allow us to return
	 // the location of where the visitor is; and other information.
	 var geo = (google.gears.factory.create("beta.geolocation"));
	 lastCallBack = callBack; // our callback function we used.
     geo.getCurrentPosition(function(gears){
	  lastCallBack(gears.gearsAddress);
	 },null,{enableHighAccuracy:true,
	 gearsRequestAddress:true});
	};
	
  }, // end of geolocate
  
  // the upload function allows you to upload single / multiple files to 
  // a remote or local server all at once; but with the capabilities of 
  // gears you can also watch the progress of upload completion.
  // @ multipleFiles: Boolean - whether or not they can upload multiple-files
  // @ putURL: String - where the files should be uploaded to.
  // @ fnProgress: Function - the function to send the progress to.
  // @ fnComplete: Function - the function to callback to when upload is complete.
  // @ installOptions: Object - whether or not we should install gears if it isn't
  upload: function(multipleFiles, putURL, fnProgress, fnComplete, installOptions){
   
    if(installOptions==null||installOptions=="undefined") 
	installOptions = {}; // create a blank object for installed function
	if(ty.gears.installed(installOptions)==true){
     // check if google gears is currently installed.
     var desktop = (google.gears.factory.create("beta.desktop"));
     desktop.openFiles(function(upload){
	  
	  // now that we got our files; we can start uploading to the server.
	  // first we need to create an http request object allowing us to send
	  // blobs to the server and allowing us to track the progression of it.
	  var httpRequest = (google.gears.factory.create("beta.httprequest"));
	  httpRequest.open("PUT", putURL); // open the recieving URL.
	  httpRequest.upload.onprogress = fnProgress; // watch the progress
	  httpRequest.onreadystatechange = function() {
	   // once the on ready state changes; make sure that we check for 
	   // what type of ready state we are currently at and check them.
	   if(httpRequest.readyState == 4) fnComplete();
	  };
	  // now that we have fully setup our http request; we can now start
	  // sending the data to the server; which will send our BLOB; also 
	  // known as Binary Large OBjects; this will trigger the progress
	  // events and eventually trigger our completion event.
	  httpRequest.send(upload[0].blob);
	  
	 }, {singleFile:multipleFiles});
	};
   
  }, // end of uploading
  
  // creates a resource store that allows you to store content
  // and use it offline; this allows you to access the page without
  // an internet connection and is great for when your on the go.
  resource: {
   
   // creates the resource store; you need a store to be
   // able to capture, and uncapture data within them.
   create: function(storeName, installOptions){
    if(installOptions==null||installOptions=="undefined") 
	installOptions = {}; // create a blank object for installed function
	if(ty.gears.installed(installOptions)==true){
	 // create the local server object using google gears.
	 var localServer = (google.gears.factory.create("beta.localserver"));
	 localServer.createStore( storeName ); // create the resource store
	 return true; // the resource store was successfully created.
	}; return false;
   }, // end of gears create();
   
   // remove the resource store; the store needs to exist
   // to remove the store else nothing will happen.
   remove: function(storeName, installOptions){
    if(installOptions==null||installOptions=="undefined") 
	installOptions = {}; // create a blank object for installed function
	if(ty.gears.installed(installOptions)==true){
	 // create the local server object using google gears.
	 var localServer = (google.gears.factory.create("beta.localserver"));
	 if(localServer.openStore( storeName )) { // check for store existence
	  localServer.removeStore( storeName ); // remove the resource store
	  return true; // we successfully removed the store
	 } else { return false; }; // store doesn't exist.
	};
   }, // end of gears remove();
   
   // this function trys and finds all the dependent files being used
   // by the current page and then returns them to you as an array.
   // @ self is the only required parameter; this is a Boolean just 
   // asking if it should include the path to the location or not.
   findPageResources: function(self){ 
	
	// this function will check to see if what we are 
	// loading is external; if it is; we will get an 
	// exception error because we cannot capture the 
	// file because there are security violations.
	function isNotExternal(page){ 
	 var url = (location.href); // the current URL
	 var myPage = new String(page);
	 if(myPage.indexOf(url)!=-1) return true 
	 else return false;
	};
	
	var resources = []; // resources found on the current page.
	// the following four variables allows us to get the main locations
	// where javascript script tags and css script tags are located. we 
	// will use this by then finding all the script and style tags.
	if(self == true) resources.push(location.pathname);
	var docJavaScriptCSS = (document.getElementsByTagName("head")[0]);
	var bodyJavaScriptCSS = (document.getElementsByTagName("body")[0]);
	// locationSrc (or) locationSource contains all the given script and style tags within the body and head tags, this will 
	// allow us to retrieve most of the included and dependent files that are being used by the page; unless it server-side.
	var locationSrc = [(docJavaScriptCSS.getElementsByTagName("script")),(docJavaScriptCSS.getElementsByTagName("style")),
	(bodyJavaScriptCSS.getElementsByTagName("script")),(bodyJavaScriptCSS.getElementsByTagName("style"))];
	
	for(var i=0;i<(locationSrc.length);i++){
	 for(var d=0;d<(locationSrc[i].length);d++){
	  var curColItem = (locationSrc[i][d]); // current HTML Collection
	  // this will return a script or style element; but we need to make 
	  // sure that it has a valid source; if it doesn't have one; then 
	  // that means it's internal and is included inside itself; which
	  // will be imported if self is set to true.
	  if(curColItem.src != null && isNotExternal(curColItem.src) == true)
	  resources.push(curColItem.src); // push the resource to end of array
	 }; // end of HTML Collection 
	}; // end of Locations Loop
	// return all the resources we found.
	return(resources); 
	
   }, // end of findPageResources();
   
   // captures the resources for a given store and then stores
   // all the given resources within the store that was specified.
   capture: function(storeName, captureFiles, fnCaptured, installOptions){
    if(installOptions==null||installOptions=="undefined") 
	installOptions = {}; // create a blank object for installed function
	if(ty.gears.installed(installOptions)==true){
	 var localServer = (google.gears.factory.create("beta.localserver"));
	 var myStore = (localServer.openStore(storeName)); // try opening the store
	 if(!myStore) return false; // store doesn't exist.
	 // try and capture all the given files from the array,
	 // then when we receive an answer; use the callback.
	 myStore.capture(captureFiles, fnCaptured);
	};
   }, // end of gears capture();
   
   // uncaptures the resources for a given store; this will remove
   // all the files passed to @captureFiles from the store; if the
   // file given to captureFiles doesn't exist; nothing will occur.
   uncapture: function(storeName, captureFiles, installOptions){
     if(installOptions==null||installOptions=="undefined") 
	 installOptions = {}; // create a blank object for installed function
	 if(ty.gears.installed(installOptions)==true){
	  var localServer = (google.gears.factory.create("beta.localserver"));
	  var myStore = (localServer.openStore(storeName)); // try opening the store
	  if(!myStore) return false; // store doesn't exist.
	  // once we open the store; we will now try to 
	  // remove all the files that were stored.
      for(var i=0;i<(captureFiles.length);i++){
	   // remove the file that was stored.
       myStore.remove(captureFiles[i]);
      } // end of removal loop
	 };
   }, // end of gears uncapture();
   
  }, // end of resource store
  
 }, // end of gears library
 
}; // end of ty Library Object

// the following functions are to make it easier when hiding, and showing 
// objects, this allows us to easily check for hide or show.  the show 
// function is re-routed to hide but with the value of show on, so that
// instead of hiding, it shows the object.
function checkShowHide(show, object){
 if(show == 1) show_object(object);
 if(show == 0) hide_object(object);
};

// this hides an object.
function hide_object(object){ with(object.style){
 visibility = 'hidden';
 display = '';
};};

// this shows an object.
function show_object(object){ with(object.style){
 visibility = 'visible';
 display = 'block';
};};

// checkObjectTag is an important function in ty Library because it allows the use
// of just ID tags to be sumbitted which can then be converted into the document 
// object.  this allows for less typing, and annoyances of typing out the DOM
// everytime you want to use a function inside the ty Library.
function checkObjectTag(object){
 
 // check if the object is a string, if it is; then 
 // try converting the object String into just an Object.
 if(typeof object == "string") { 
  // check if the object is an Object
  if(document.getElementById(object)) { 
   // the object String was an Object, return it.
   return(document.getElementById(object));
  } else {
   // the object String was not an Object, so we will return false; when 
   //comparing with this function you want to make sure to search for false, 
   // which obviously means that the Object doesn't exist.
   return false; 
  };
 };
 
 // check if the given object is already an Object,
 // and if it is ; just return the given Object.
 if(typeof object == "object") { 
  // if Object exists... then return it.
  if(object) { return(object);
 };};
 
};

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

function Delegate(){}
 Delegate.create = function(o,f) {
 var a = new Array() ;
 var l = arguments.length ;
 for(var i = 2 ; i < l ; i++) a[i - 2] = arguments[i] ;
 return function() {
  var aP = [].concat(arguments, a) ;
  f.apply(o, aP);
}};

// this is the main function call when using the Tweener class; it calls
// for the object's style, what property you want to manipulate, what easing
// you want, the beginning value, and ending value, how long it will last, 
// and the suffix; such as px, em, in, etc...
Tween = function(obj, prop, func, begin, finish, duration, suffixe){
 this.init(obj, prop, func, begin, finish, duration, suffixe)
};

// now we create the tweener object and set all the default 
// properties incase the person who uses this doesn't want
// to set the property but use a default value instead.
var t = Tween.prototype;
t.obj = new Object();
t.prop='';
t.func = function (t, b, c, d) { return c*t/d + b; };
t.begin = 0;
t.change = 0;
t.prevTime = 0;
t.prevPos = 0;
t.looping = false;
t._duration = 0;
t._time = 0;
t._pos = 0;
t._position = 0;
t._startTime = 0;
t._finish = 0;
t.name = '';
t.suffixe = '';
t._listeners = new Array();	
t.setTime = function(t){
this.prevTime = this._time;

if(t>this.getDuration()){
 if(this.looping){
  this.rewind (t - this._duration);
  this.update();
  this.broadcastMessage('onMotionLooped',{target:this,type:'onMotionLooped'});
 }else{
  this._time = this._duration;
  this.update();
  this.stop();
  this.broadcastMessage('onMotionFinished',{target:this,type:'onMotionFinished'});
 }
}else if(t<0){
 this.rewind();
 this.update();
}else{
 this._time = t;
 this.update();
};};
 
t.getTime = function(){return this._time;}
t.setDuration = function(d){this._duration = (d == null || d <= 0) ? 100000 : d;}
t.getDuration = function(){return this._duration;}
t.setPosition = function(p){
 this.prevPos = this._pos;
 var a = this.suffixe != '' ? this.suffixe : '';
 this.obj[this.prop] = Math.round(p) + a;
 this._pos = p;
 this.broadcastMessage('onMotionChanged',{target:this,type:'onMotionChanged'});
};

t.getPosition = function(t){
 if(t==undefined) t = this._time;
 return this.func(t, this.begin, this.change, this._duration);
};

t.setFinish = function(f){this.change = f - this.begin;};
t.getFinish = function(){return this.begin + this.change;};
t.init = function(obj, prop, func, begin, finish, duration, suffixe){
 if(!arguments.length)return;
 this._listeners = new Array();
 this.addListener(this);
 if(suffixe) this.suffixe = suffixe;
 this.obj = obj;
 this.prop = prop;
 this.begin = begin;
 this._pos = begin;
 this.setDuration(duration);
 if(func!=null && func!='') {
  this.func = func;
 };
 this.setFinish(finish);
};

t.start = function(){
 this.rewind();
 this.startEnterFrame();
 this.broadcastMessage('onMotionStarted',{target:this,type:'onMotionStarted'});
};

t.rewind = function(t){
 this.stop();
 this._time = (t == undefined) ? 0 : t;
 this.fixTime();
 this.update();
};

t.fforward = function(){
 this._time = this._duration;
 this.fixTime();
 this.update();
};

t.update = function(){
 this.setPosition(this.getPosition(this._time));
};

t.startEnterFrame = function(){
 this.stopEnterFrame();
 this.isPlaying = true;
 this.onEnterFrame();
};

t.onEnterFrame = function(){
 if(this.isPlaying) {
  this.nextFrame();
  setTimeout(Delegate.create(this, this.onEnterFrame), 0);
 };
};

t.nextFrame = function(){this.setTime((this.getTimer() - this._startTime) / 1000);};

t.stop = function(){
 this.stopEnterFrame();
 this.broadcastMessage('onMotionStopped',{target:this,type:'onMotionStopped'});
};

t.stopEnterFrame = function(){this.isPlaying = false;};
t.continueTo = function(finish, duration){
 this.begin = this._pos;
 this.setFinish(finish);
 if(this._duration != undefined)
 this.setDuration(duration);
 this.start();
};

t.resume = function(){
 this.fixTime();
 this.startEnterFrame();
 this.broadcastMessage('onMotionResumed',{target:this,type:'onMotionResumed'});
};

t.yoyo = function (){this.continueTo(this.begin,this._time);}
t.addListener = function(o){
 this.removeListener (o);
 return this._listeners.push(o);
};

t.removeListener = function(o){
 var a = this._listeners;	
 var i = a.length;
 while(i--){
  if(a[i]==o){
   a.splice (i, 1);
   return true;
  };};
 return false;
};

t.broadcastMessage = function(){
 var arr = new Array();
 for(var i = 0; i < arguments.length; i++){
  arr.push(arguments[i])
 };
 var e = arr.shift();
 var a = this._listeners;
 var l = a.length;
 for (var i=0; i<l; i++){
  if(a[i][e])
  a[i][e].apply(a[i], arr);
 };
};

t.fixTime = function(){this._startTime = this.getTimer() - this._time * 1000;};
t.getTimer = function(){return new Date().getTime() - this._time;};

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// The following tweening equations are provided by Robert Penner from his personal
// website http://www.robertpenner.com/.  The equations were originally written for
// ActionScript; the powerful language used in Flash, but they have been ported left
// and right for many other languages to be used; like JavaScript.

Tween.backEaseIn = function(t,b,c,d,a,p){
 if(s == undefined) var s = 1.70158;
 return c*(t/=d)*t*((s+1)*t-s)+b;
};

Tween.backEaseOut = function(t,b,c,d,a,p){
 if(s==undefined) var s = 1.70158;
 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
};

Tween.backEaseInOut = function(t,b,c,d,a,p){
 if(s == undefined) var s = 1.70158; 
 if((t/=d/2)<1) return c/2*(t*t*(((s*=(1.525))+1)*t-s))+b;
 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t+s)+2) + b;
};

Tween.elasticEaseIn = function(t,b,c,d,a,p){
 if(t==0) return b; if((t/=d)==1) return b+c;  
 if(!p) p=d*.3; if(!a || a<Math.abs(c)){
  a=c; var s=p/4;
 } else {
  var s = p/(2*Math.PI) * Math.asin (c/a);
 };
 return -(a*Math.pow(2,10*(t-=1)) * 
 Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
};

Tween.elasticEaseOut = function (t,b,c,d,a,p){
 if(t==0) return b;  if((t/=d)==1) return b+c;  if(!p) p=d*.3;
 if (!a || a < Math.abs(c)) { a=c; var s=p/4; }
  else var s = p/(2*Math.PI) * Math.asin (c/a);
  return (a*Math.pow(2,-10*t) * Math.sin((t*d-s)*(2*Math.PI)/p )+c+b);
};

Tween.elasticEaseInOut = function (t,b,c,d,a,p){
 if(t==0) return b;  if((t/=d/2)==2) return b+c;  if(!p) var p=d*(.3*1.5);
 if(!a || a < Math.abs(c)) {var a=c; var s=p/4; }
 else var s = p/(2*Math.PI) * Math.asin (c/a);
 if(t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
};

Tween.bounceEaseOut = function(t,b,c,d){
 if((t/=d) < (1/2.75)){
  return c*(7.5625*t*t)+b;
 }else if(t < (2/2.75)){
  return c*(7.5625*(t-=(1.5/2.75))*t+.75)+b;
 }else if(t < (2.5/2.75)){
  return c*(7.5625*(t-=(2.25/2.75))*t+.9375)+b;
 }else{
  return c*(7.5625*(t-=(2.625/2.75))*t+.984375)+b;
 };
};

Tween.bounceEaseIn = function(t,b,c,d){
 return c - Tween.bounceEaseOut (d-t, 0, c, d) + b;
};

Tween.bounceEaseInOut = function(t,b,c,d){
 if (t < d/2) return Tween.bounceEaseIn (t*2, 0, c, d) * .5 + b;
 else return Tween.bounceEaseOut (t*2-d, 0, c, d) * .5 + c*.5 + b;
};


Tween.regularEaseIn = function(t,b,c,d){ return c*(t/=d)*t + b; };
Tween.regularEaseOut = function(t,b,c,d){ return -c *(t/=d)*(t-2) + b; };
Tween.regularEaseInOut = function(t,b,c,d){
 if ((t/=d/2) < 1) return c/2*t*t + b;
 return -c/2 * ((--t)*(t-2) - 1) + b;
};

Tween.strongEaseIn = function(t,b,c,d){ return c*(t/=d)*t*t*t*t + b; };
Tween.strongEaseOut = function(t,b,c,d){ return c*((t=t/d-1)*t*t*t*t + 1) + b; };
Tween.strongEaseInOut = function(t,b,c,d){
 if((t/=d/2) < 1) return c/2*t*t*t*t*t+b;
 return c/2*((t-=2)*t*t*t*t + 2)+b;
};

var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener("load",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener("load",Y,false)}else{if(typeof O.attachEvent!=D){i(O,"onload",Y)}else{if(typeof O.onload=="function"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName("body")[0];var aa=C(r);aa.setAttribute("type",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable("$version");if(ab){ab=ab.split(" ")[1].split(",");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute("name").toLowerCase()!="movie"){ah[X[ad].getAttribute("name")]=X[ad].getAttribute("value")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName=="OBJECT"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F("6.0.65")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName=="OBJECT"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width="310"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height="137"}j.title=j.title.slice(0,47)+" - Flash Player Installation";var ad=M.ie&&M.win?"ActiveX":"PlugIn",ac="MMredirectURL="+O.location.toString().replace(/&/g,"%26")+"&MMplayerType="+ad+"&MMdoctitle="+j.title;if(typeof ab.flashvars!=D){ab.flashvars+="&"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C("div");X+="SWFObjectNew";Y.setAttribute("id",X);ae.parentNode.insertBefore(Y,ae);ae.style.display="none";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C("div");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display="none";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C("div");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName=="PARAM")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah="";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()=="data"){ag.movie=ai[ae]}else{if(ae.toLowerCase()=="styleclass"){ah+=' class="'+ai[ae]+'"'}else{if(ae.toLowerCase()!="classid"){ah+=" "+ae+'="'+ai[ae]+'"'}}}}}var af="";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name="'+ad+'" value="'+ag[ad]+'" />'}}aa.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+ah+">"+af+"</object>";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+="";ag+="";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+="&"+ai+"="+Z[ai]}else{am.flashvars=ai+"="+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\?/.test(Z)){Z=Z.split("?")[1]}if(aa==null){return L(Z)}var Y=Z.split("&");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf("="))==aa){return L(Y[X].substring((Y[X].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display="block"}}if(E){E(B)}}a=false}}}}();

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

// following parameters are easier methods to type, this is not needed, 
// but helps and allows for customizing what character you want to use.
var $ = ty;

