/**
 * jQuery.scale
 * 
 * jQuery extention for scaling an object to fit inside its parent while
 * maintaining the aspect ratio. See demo at 
 * http://static.robmd.net/jquery.scale/demo
 * 
 * Usage:
 *      $('foo').scale(String[, String][, string]) 
 *
 *      Where $('foo') is a jQuery reference to be scaled.
 *
 * Parameters:
 *      In any order, enter "center" (to center the object) and/or "stretch" 
 *      (to stretch the object to fit inside the parent) and/or "debug" (to 
 *      turn on verbose logging)
 * 
 * Returns:
 *      The same jQuery object, for chaining.
 *
 * By Rob McGuire-Dale (http://robmd.net), September 2009
 * 
 * jQuery plugin structure based on "A Really Simple jQuery Plugin Tutorial" 
 * (http://www.queness.com/post/112/a-really-simple-jquery-plugin-tutorial) by
 * Kevin Liew
 *
 * Copyright (c) 2009 to current, OSU Open Source Lab (http://osuosl.org)
 * Dual-licensed under GPLv2 and the MIT License.
 */

(function($){                               // anonymous function wrapper
    $.fn.extend({                           // attach new method to jQuery
        scale: function(arg1, arg2, arg3){  // declare plugin name/parameters
        
            // iterate over current set of matched elements
            return this.each(function(){
                safelog( "jquery.scale is starting...");
                
                safelog( "jquery.scale: Using browser \"" + navigator.appName +
                    "\" version \"" + navigator.appVersion + "\"");

                // parse the arguments into flags
                var center = false;
                var stretch = false;
                var debug = false;
                if(arg1 == "center" || arg2 == "center" || arg3 == "center")
                    center = true;
                if(arg1 == "stretch" || arg2 == "stretch" || arg3 == "stretch")
                    stretch = true;
                if(arg1 == "debug" || arg2 == "debug" || arg3 == "debug")
                    debug = true;
            
                // capture the object
                var obj = $(this);
                
                // if this is the plugin's first run on the object, and the
                // object is an image, force a reload
                if(obj.attr('src') && 
                        !obj.data('jquery_scale_orig-height')){
                    
                    safelog("jquery.scale: object is an image");
                    var date = new Date();
                    var cursrc = obj.attr("src");
                    var newsrc = cursrc;
                    if( cursrc.indexOf('?') != -1 )
                        newsrc = cursrc.substring(0, cursrc.indexOf('?'));
                    newsrc = newsrc + "?" + date.getTime();
                    obj.attr( "src", newsrc );
                    safelog( "jquery.scale: img src changed to " + newsrc + 
                        " to force a reload");
					// For I.E. 6-8 support as it requires a new image for 
                    // scaling (see issue #3)
					if($.support.leadingWhitespace)
						obj.attr("src", cursrc);
                    this.onload = scale;
                    
                } else {
                    safelog("jquery.scale: object is NOT an image");
                    scale();
                }
                
                // plugin's main function
                function scale(){
                    // if this is the plugin's first run on the object, capture
                    // the object's original dimensions
                    if(!obj.data('jquery_scale_orig-height')){
                        
                        obj.data('jquery_scale_orig-height', obj.height());
                        obj.data('jquery_scale_orig-width', obj.width());
                        
                        safelog("jquery.scale: is starting for the first " + 
                            "time. Captured the original dimensions of " + 
                            obj.width() + "x" + obj.height());
                    
                    // if this is NOT the plugin's first run on the object,
                    // reset the object's dimensions
                    } else {           
                        obj.height(obj.data('jquery_scale_orig-height'));
                        obj.width(obj.data('jquery_scale_orig-width'));
                        
                        safelog("jquery.scale: has been run before. Reset " +
                            "the object to its original dimensions of " + 
                            obj.width() + "x" + obj.height());
                    }

                    safelog("jquery.scale: BEFORE scaling, object's outer " +
                        "size = " + obj.outerWidth() + "x" + 
                        obj.outerHeight() + ", object's parent's inner size "
                        + "= " + obj.parent().width() + "x" + 
                        obj.parent().height());
                    
                    // Object too tall, but width is fine. Need to shorten.
                    if(obj.outerHeight() > obj.parent().height() && 
                       obj.outerWidth() <= obj.parent().width()){

                        safelog("jquery.scale: object is too tall, but width"
                            + " is OK" );
                        matchHeight();       
                    }
                    
                    // Object too wide, but height is fine. Need to diet.
                    else if(obj.outerWidth() > obj.parent().width() && 
                            obj.outerHeight() <= obj.parent().height()){

                        safelog( "jquery.scale: object is too wide, but " +
                            "height is OK" );
                        matchWidth();    
                    }
                    
                    // Object too short and skinny. If "stretch" option 
                    // enabled, match the dimenstion that is closer to being
                    // correct.
                    else if(obj.outerWidth() < obj.parent().width() && 
                            obj.outerHeight() < obj.parent().height() &&
                            stretch){
                      
                        safelog( "jquery.scale: object is too short and " +
                            "skinny, and stretch option enabled" );
                        if( obj.parent().height()/obj.outerHeight() <= 
                            obj.parent().width()/obj.outerWidth()){
                            
                            safelog( "jquery.scale: height is closer to " +
                                "being correct, or height and width are " +
                                "equally close to being correct");
                            matchHeight();
                            
                        } else {
                            safelog( "jquery.scale: width is closer to being "
                                + "correct");
                            matchWidth();
                        }
                    
                    // Object too tall and wide. Need to match the dimension 
                    // that is further from being correct.
                    } else if(obj.outerWidth() > obj.parent().width() && 
                               obj.outerHeight() > obj.parent().height()){
                               
                        safelog("jquery.scale: object is too tall and wide");
                        if( obj.parent().height()/obj.outerHeight(  ) >
                            obj.parent().width()/obj.outerWidth(  ) ){
                            
                            safelog("jquery.scale: width is closer to being "
                                + "correct");
                            matchWidth();
                            
                        } else {
                            safelog("jquery.scale: height is closer to " +
                                "being correct, or height and width are " +
                                "equally close to being correct");
                            matchHeight();
                        }                            

                    }//else, object is the same size as the parent. Do nothing.

                    // if the center option is enabled, also center the object 
                    // within the parent
                    if(center){
                        safelog("jquery.scale: centering option enabled" );
                        obj.css('position', 'relative' );
                        obj.css('margin-top', 
                             obj.parent().height()/2 - 
                                        obj.outerHeight()/2);
                        obj.css('margin-left', 
                             obj.parent().width()/2 - 
                                        obj.outerWidth()/2);
                    }

                    // reset the onload pointer so the object doesn't flicker
                    // when reloaded other ways.
                    this.onload = null;

                    safelog("jquery.scale: AFTER scaling, object's size = " +
                        obj.outerWidth() + "x" + obj.outerHeight() + 
                        ", object's parent's size = " + 
                        obj.parent().width() + "x" + 
                        obj.parent().height() + ".'");                    
                
                }   //END scale
                
                // match the height while maintaining the aspect ratio
                function matchHeight(){
                    safelog("jquery.scale: matching height");
                    obj.width( obj.outerWidth() * 
                        obj.parent().height()/obj.outerHeight() - 
                        (obj.outerWidth() - obj.width()));
                    obj.height(obj.parent().height() - 
                        (obj.outerHeight() - obj.height()));
                }
                
                // match the width while maintaining the aspect ratio
                function matchWidth(){
                    safelog("jquery.scale: matching width");
                    obj.height(obj.outerHeight() * 
                        obj.parent().width()/obj.outerWidth() - 
                        (obj.outerHeight() - obj.height()));
                    obj.width( obj.parent().width() - 
                        (obj.outerWidth() - obj.width()));
                }
                
                // a function to safely log
                function safelog(msg){ 
                    if(window.console && debug){
                        console.log( msg );
                    }
                }
                            
            });     //END matched element iterations
        }           //END plugin declaration
    });             //END new jQuery method attachment
})(jQuery);         //END anonymous function wrapper

