﻿/*************************************************
**  jQuery Masonry version 1.3.2
**  Copyright David DeSandro, licensed MIT
**  http://desandro.com/resources/jquery-masonry
**************************************************/
;(function($){  

  /*!
   * smartresize: debounced resize event for jQuery
   * http://github.com/lrbabe/jquery-smartresize
   *
   * Copyright (c) 2009 Louis-Remi Babe
   * Licensed under the GPL license.
   * http://docs.jquery.com/License
   *
   */
  var event = $.event,
      resizeTimeout;

  event.special.smartresize = {
    setup: function() {
      $(this).bind( "resize", event.special.smartresize.handler );
    },
    teardown: function() {
      $(this).unbind( "resize", event.special.smartresize.handler );
    },
    handler: function( event, execAsap ) {
      // Save the context
      var context = this,
          args = arguments;

      // set correct event type
      event.type = "smartresize";

      if (resizeTimeout) { clearTimeout(resizeTimeout); }
      resizeTimeout = setTimeout(function() {
        jQuery.event.handle.apply( context, args );
      }, execAsap === "execAsap"? 0 : 100);
    }
  };

  $.fn.smartresize = function( fn ) {
    return fn ? this.bind( "smartresize", fn ) : this.trigger( "smartresize", ["execAsap"] );
  };



  // masonry code begin
  $.fn.masonry = function(options, callback) { 

    // all my sweet methods
    var msnry = {
      getBricks : function($wall, props, opts) {
        var hasItemSelector = (opts.itemSelector === undefined);
		
        if ( opts.appendedContent === undefined ) {
          // if not appendedContent
          props.$bricks = hasItemSelector ?
                $wall.children() :
                $wall.find(opts.itemSelector);
        } else {
         //  if appendedContent...
         props.$bricks = hasItemSelector ?
                opts.appendedContent : 
                opts.appendedContent.filter( opts.itemSelector );
        }
		
		props.$bricks = props.$bricks.not("script");
      },
	  
      placeDummyBrick : function($brick, props, opts, col, shortCol, height, setHeight) {
			$new_brick = [];
			
			if(props.dummy && ((props.dummy.position.top != props.colY_b[ shortCol + col ]) || (props.dummy.dimension.height != setHeight - props.colY_b[ shortCol + col ] - height)))
			{
				props.dummy.dimension.width = props.dummy.colCount * props.colW;
				
			   $brick.after('<div class="dummy-brick fill-box"></div>');
			   
			   $new_brick = $brick.next().css({position: "absolute", height : props.dummy.dimension.height - ($brick.parents("#site-features").length ? 6 : ($brick.parents(".artists").length ? 14 : 11)), width : props.dummy.dimension.width - ($brick.parents("#site-features").length ? 6 : 14), top : props.dummy.position.top, left : props.dummy.position.left, margin : 0});

				props.dummy = null;
			}
		
        	if(setHeight > props.colY_b[ shortCol + col ] + height)
			{
				props.dummy = props.dummy || {colCount : 0, position : { top : props.colY_b[ shortCol + col ], left : props.colW * (shortCol + col) + props.posLeft}, dimension : {height : setHeight - props.colY_b[ shortCol + col ] - height}};
				props.dummy.colCount++;
			} 
			
			if($new_brick.length)
			{
				$brick = $new_brick;
			}
			
			return $brick;
	  },
      
      placeBrick : function($brick, setCount, setY, props, opts) {     
            // get the minimum Y value from the columns...
        var minimumY = Math.min.apply(Math, setY),
			height = $brick.outerHeight(true),
            setHeight = minimumY + height,
            i = setY.length,
            shortCol = i,
            setSpan = props.colCount + 1 - i; 
        // Which column has the minY value, closest to the left
        while (i--) {
          if ( setY[i] == minimumY ) {
            shortCol = i;
          }
        }
      
        var position = {
		  position: "absolute",
          left: props.colW * shortCol + props.posLeft,
          top: minimumY
        };

	 	//msnry.placeDummyBrick($brick, position, {width: 100, height: 100}, props, opts);
	 
        // position the brick
        $brick.applyStyle(position, $.extend(true,{},opts.animationOptions) );

        // apply setHeight to necessary columns
		props.colY_b = [];
		for(var i = 0; i < props.colY.length; i++)
		{
			props.colY_b[i] = props.colY[i];
		}
		
        for ( i=0; i < setSpan; i++ ) {		  
		  props.colY[ shortCol + i ] = setHeight;
		
			msnry.placeDummyBrick($brick, props, opts, i, shortCol, height, setHeight);	
		} 
      },
      
      setup : function($wall, opts, props) {
        msnry.getBricks($wall, props, opts);

        if ( props.masoned ) {
          props.previousData = $wall.data('masonry');
        }

        if ( opts.columnWidth === undefined) {
          props.colW = props.masoned ?
              props.previousData.colW :
              props.$bricks.outerWidth(true);
        } else {
          props.colW = opts.columnWidth;
        }

        props.colCount = Math.floor( $wall.width() / props.colW ) ;
        props.colCount = Math.max( props.colCount, 1 );
      },
      
      arrange : function($wall, opts, props) {
		var i;
		props.$bricks = props.$bricks.not(".dummy-brick");	
		
        if ( !props.masoned || opts.appendedContent !== undefined ) {
          // just the new bricks
		  //props.$bricks.css( 'position', 'absolute' );
        }
		else
		{
			$wall.children(".dummy-brick").remove();
		}

        // if masonry hasn't been called before
        if ( !props.masoned ) { 
          $wall.css( 'position', 'relative' );

          // get top left position of where the bricks should be
          var $cursor = $( document.createElement('div') );
          $wall.prepend( $cursor );
          props.posTop =  Math.round( $cursor.position().top );
          props.posLeft = Math.round( $cursor.position().left );
          $cursor.remove();
        } else {
          props.posTop =  props.previousData.posTop;
          props.posLeft = props.previousData.posLeft;
        }
        
        // set up column Y array
        if ( props.masoned && opts.appendedContent !== undefined ) {
          // if appendedContent is set, use colY from last call
          props.colY = props.previousData.colY;

          /*
          *  in the case that the wall is not resizeable,
          *  but the colCount has changed from the previous time
          *  masonry has been called
          */
          for ( i = props.previousData.colCount; i < props.colCount; i++) {
            props.colY[i] = props.posTop;
          }

        } else {
          // start new colY array, with starting values set to posTop
          props.colY = [];
          i = props.colCount;
          while (i--) {
            props.colY.push(props.posTop);
          }
        }

        // are we animating the rearrangement?
        // use plugin-ish syntax for css or animate
        $.fn.applyStyle = ( props.masoned && opts.animate ) ? $.fn.animate : $.fn.css;


        // layout logic
        if ( opts.singleMode ) {
          props.$bricks.each(function(){
            var $brick = $(this);
            msnry.placeBrick($brick, props.colCount, props.colY, props, opts);
          });      
        } else {
		 var brick_count = props.$bricks.length;
		 
          props.$bricks.each(function(index) {
            var $brick = $(this),
                //how many columns does this brick span
                colSpan = Math.ceil( $brick.outerWidth(true) / props.colW);
            colSpan = Math.min( colSpan, props.colCount );

            if ( colSpan === 1 ) {
              // if brick spans only one column, just like singleMode
              msnry.placeBrick($brick, props.colCount, props.colY, props, opts);
            } else {
              // brick spans more than one column

              //how many different places could this brick fit horizontally
              var groupCount = props.colCount + 1 - colSpan,
                  groupY = [];

              // for each group potential horizontal position
              for ( i=0; i < groupCount; i++ ) {
                // make an array of colY values for that one group
                var groupColY = props.colY.slice(i, i+colSpan);
                // and get the max value of the array
                groupY[i] = Math.max.apply(Math, groupColY);
              }
              msnry.placeBrick($brick, groupCount, groupY, props, opts);
            }
			
			if(index + 1 == brick_count)
			{
				var maximumY = Math.max.apply(Math, props.colY),
					setHeight = maximumY;

				props.colY_b = []; 
				for(var i = 0; i < props.colY.length; i++)
				{
					props.colY_b[i] = props.colY[i];
					$brick = msnry.placeDummyBrick($brick, props, opts, i, 0, 0, setHeight);	
				}
				msnry.placeDummyBrick($brick, props, opts, i + 1, 0, 0, setHeight);				
			}
          }); 
		  
		  //    /props.bricks.each(function() {
        }  //     /layout logic

        // set the height of the wall to the tallest column
        props.wallH = Math.max.apply(Math, props.colY);
        var wallCSS = { height: props.wallH - props.posTop };
        $wall.applyStyle( wallCSS, $.extend(true,[],opts.animationOptions) );

        // add masoned class first time around
        if ( !props.masoned ) { 
          // wait 1 millisec for quell transitions
          setTimeout(function(){
            $wall.addClass('masoned'); 
          }, 1);
        }

        // provide props.bricks as context for the callback
        callback.call( props.$bricks );

        // set all data so we can retrieve it for appended appendedContent
        //    or anyone else's crazy jquery fun
        $wall.data('masonry', props );
        
      }, // /msnry.arrange
      
      resize : function($wall, opts, props) {
        props.masoned = !!$wall.data('masonry');
        var prevColCount = $wall.data('masonry').colCount;
		
        msnry.setup($wall, opts, props);
        if ( props.colCount != prevColCount ) {
          msnry.arrange($wall, opts, props);
        }
      }
    };


    /*
    *  let's begin
    *  IN A WORLD...
    */
    return this.each(function() {  

      var $wall = $(this),
          props = {};

      // checks if masonry has been called before on this object
      props.masoned = !!$wall.data('masonry');
    
      var previousOptions = props.masoned ? $wall.data('masonry').options : {},
          opts =  $.extend(
                    {},
                    $.fn.masonry.defaults,
                    previousOptions,
                    options
                  ),
          resizeOn = previousOptions.resizeable;

      // should we save these options for next time?
      props.options = opts.saveOptions ? opts : previousOptions;

      //picked up from Paul Irish
      callback = callback || function(){};

      msnry.getBricks($wall, props, opts);

      // if brickParent is empty, do nothing, go back home and eat chips
      if ( !props.$bricks.length ) { 
        return this; 
      }

      // call masonry layout
      msnry.setup($wall, opts, props);
      msnry.arrange($wall, opts, props);
    
      // binding window resizing
      if ( !resizeOn && opts.resizeable ) {
        $(window).bind('smartresize.masonry', function() { msnry.resize($wall, opts, props); } );
      }
      if ( resizeOn && !opts.resizeable ) { 
        $(window).unbind('smartresize.masonry'); 
      }
       

    });    //    /return this.each(function()
  };      //    /$.fn.masonry = function(options)


  // Default plugin options
  $.fn.masonry.defaults = {
    singleMode: false,
    columnWidth: undefined,
    itemSelector: undefined,
    appendedContent: undefined,
    saveOptions: true,
    resizeable: true,
    animate: false,
    animationOptions: {}
  };

})(jQuery);
