(function () {

  $.extend($.ui.draggable.defaults, {
    guide : true,
    guidecolor : ['blue', 'red', 'green', 'yellow'],
    guidestyle : ['dashed'],
    guideinner : false,
    guidecenter : true,
    guidepadding : 0
  });

  $.ui.plugin.add("draggable", "guides", {
  	start: function(event, ui) {

  		var i = $(this).data("draggable"), o = i.options;
  		i.guideElements = [];

  		$(o.guides.constructor != String ? ( o.guides.items || ':data(draggable)' ) : o.guides).each(function() {

  			var $t = $(this);
  			var $o = $t.offset();

  			if (this != i.element[0]) i.guideElements.push({

  				item: this,
  				width: $t.outerWidth(),
  				height: $t.outerHeight(),
  				top: $o.top,
  				left: $o.left,
  				inner: false
  			});
  		});

      if (o.guideinner) {

    		$(o.guideinner).each(function() {
  
    			var $t = $(this);
    			var $o = $t.offset();
  
    			i.guideElements.push({
  
    				item: this,
    				width: $t.outerWidth(),
    				height: $t.outerHeight(),
    				top: $o.top,
    				left: $o.left,
    				inner: true
    			});
    		});
  		}
  	},

  	drag: function(event, ui) {

  		var i = $(this).data("draggable"),
  		  o = i.options,
  		  ih = i.helperProportions,
  		  im = i.margins,
  		  d = o.snapTolerance,
  		  p = o.guidepadding,
  		  g = o.guide,
  		  s = o.guidestyle,
  		  cg = o.guidecenter,
  		  c1 = o.guidecolor[0],
  		  c2 = o.guidecolor[1],
  		  c3 = o.guidecolor[2],
  		  c4 = o.guidecolor[3],
  		  x1 = ui.offset.left,
  		  x2 = x1 + ih.width,
  		  y1 = ui.offset.top,
  		  y2 = y1 + ih.height;

  		for (var n = i.guideElements.length - 1; n >= 0; n--){

  			var l = i.guideElements[n].left,
  		    r = l + i.guideElements[n].width,
  		    t = i.guideElements[n].top,
  		    b = t + i.guideElements[n].height,
  		    ip = i.guideElements[n].inner,
  		    lp = l - p,
  		    rp = r + p,
  		    tp = t - p,
  		    bp = b + p,
  		    li = l + p,
  		    ri = r - p,
  		    ti = t + p,
  		    bi = b - p,
  		    cv = l + ((i.guideElements[n].width - ih.width) / 2),
  		    ch = t + ((i.guideElements[n].height - ih.height) / 2),
    		  xc = l + (i.guideElements[n].width / 2),
    		  yc = t + (i.guideElements[n].height / 2);

   			if (cg && cv - d < x1 && cv + d > x1) {  //Center Vert SNAP ;)

  				ui.position.left = i._convertPositionTo("relative", {left: cv}).left - im.left;

          if (g) drawGuide(t, y2, y1, b, xc, c3, 1, s);
        }

   			if (cg && ch - d < y1 && ch + d > y1) {  //Center Horz SNAP ;)

  				ui.position.top = i._convertPositionTo("relative", {top: ch}).top - im.top;

          if (g) drawGuide(l, x2, x1, r, yc, c3, 0, s);
        }

   			if (t - d < y1 && t + d > y1) { //Top SNAP ;)

  				ui.position.top = i._convertPositionTo("relative", {top: t}).top - im.top;

          if (g) drawGuide(l, x2, x1, r, t, c1, 0, s);
        } else if (t - d < y2 && t + d > y2) {

          ui.position.top = i._convertPositionTo("relative", {top: t - ih.height}).top - im.top;

          if (g) drawGuide(l, x2, x1, r, t, c1, 0, s);
        } else if (p > 0 && !ip && tp - d < y2 && tp + d > y2) {

          ui.position.top = i._convertPositionTo("relative", {top: tp - ih.height}).top - im.top;

          if (g) drawGuide(l, x2, x1, r, tp, c2, 0, s);
        } else if (p > 0 && ip && ti - d < y1 && ti + d > y1) {

          ui.position.top = i._convertPositionTo("relative", {top: ti}).top - im.top;

          if (g) drawGuide(l, x2, x1, r, ti, c4, 0, s);
        }

        if (l - d < x1 && l + d > x1) { //Left SNAP ;)

  				ui.position.left = i._convertPositionTo("relative", {left: l}).left - im.left;

          if (g) drawGuide(t, y2, y1, b, l, c1, 1, s);
        } else if (l - d < x2 && l + d > x2) {

          ui.position.left = i._convertPositionTo("relative", {left: l - ih.width}).left - im.left;

          if (g) drawGuide(t, y2, y1, b, l, c1, 1, s);
        } else if (p > 0 && !ip && lp - d < x2 && lp + d > x2) {

          ui.position.left = i._convertPositionTo("relative", {left: lp - ih.width}).left - im.left;

          if (g) drawGuide(t, y2, y1, b, lp, c2, 1, s);
        } else if (p > 0 && ip && li - d < x1 && li + d > x1) {

          ui.position.left = i._convertPositionTo("relative", {left: li}).left - im.left;

          if (g) drawGuide(t, y2, y1, b, li, c4, 1, s);
        }

        if (b - d < y1 && b + d > y1) { //Bottom SNAP ;)

          ui.position.top = i._convertPositionTo("relative", {top: b}).top - im.top;

          if (g) drawGuide(l, x2, x1, r, b - 1, c1, 0, s);
        } else if (b - d < y2 && b + d > y2) {

          ui.position.top = i._convertPositionTo("relative", {top: b - ih.height}).top - im.top;

          if (g) drawGuide(l, x2, x1, r, b - 1, c1, 0, s);
        } else if (p > 0 && !ip && bp - d < y1 && bp + d > y1) {

          ui.position.top = i._convertPositionTo("relative", {top: bp}).top - im.top;

          if (g) drawGuide(l, x2, x1, r, bp - 1, c2, 0, s);
        } else if (p > 0 && ip && bi - d < y2 && bi + d > y2) {

          ui.position.top = i._convertPositionTo("relative", {top: bi - ih.height}).top - im.top;

          if (g) drawGuide(l, x2, x1, r, bi - 1, c4, 0, s);
        }

        if (r - d < x1 && r + d > x1) { //Right SNAP ;)

          ui.position.left = i._convertPositionTo("relative", {left: r}).left - im.left;

          if (g) drawGuide(t, y2, y1, b, r - 1, c1, 1, s);
        } else if (r - d < x2 && r + d > x2) {

          ui.position.left = i._convertPositionTo("relative", {left: r - ih.width}).left - im.left;

          if (g) drawGuide(t, y2, y1, b, r - 1, c1, 1, s);
        } else if (p > 0 && !ip && rp - d < x1 && rp + d > x1) {

          ui.position.left = i._convertPositionTo("relative", {left: rp}).left - im.left;

          if (g) drawGuide(t, y2, y1, b, rp - 1, c2, 1, s);
        } else if (p > 0 && ip && ri - d < x2 && ri + d > x2) {

          ui.position.left = i._convertPositionTo("relative", {left: ri - ih.width}).left - im.left;

          if (g) drawGuide(t, y2, y1, b, ri - 1, c4, 1, s);
        }
  		}
  	}
  });

  $.extend($.ui.resizable.defaults, {
    guide : true,
    guidecolor : ['blue', 'red', 'green', 'yellow'],
    guidestyle : ['dashed'],
    guideinner : false,
    guidecenter : true,
    guidepadding : 0,
		snapTolerance: 20
  });

  $.ui.plugin.add("resizable", "guides", {
  	start: function(event, ui) {

  		var i = $(this).data("resizable"), o = i.options;
  		i.guideElements = [];

  		$(o.guides.constructor != String ? ( o.guides.items || ':data(resizable)' ) : o.guides).each(function() {

  			var $t = $(this);
  			var $o = $t.offset();

  			if (this != i.element[0]) i.guideElements.push({

  				item: this,
  				width: $t.outerWidth(),
  				height: $t.outerHeight(),
  				top: $o.top,
  				left: $o.left,
  				inner: false
  			});
  		});
      if (o.guideinner) {

    		$(o.guideinner).each(function() {
  
    			var $t = $(this);
    			var $o = $t.offset();
  
    			i.guideElements.push({
  
    				item: this,
    				width: $t.outerWidth(),
    				height: $t.outerHeight(),
    				top: $o.top,
    				left: $o.left,
    				inner: true
    			});
    		});
  		}
  	},

  	resize: function(event, ui) {

  		var i = $(this).data("resizable"),
  		  o = i.options,
  		  p = o.guidepadding,
  		  g = o.guide,
  		  s = o.guidestyle,
  		  d = o.snapTolerance,
  		  cg = o.guidecenter,
  		  c1 = o.guidecolor[0],
  		  c2 = o.guidecolor[1],
  		  c3 = o.guidecolor[2],
  		  c4 = o.guidecolor[3],
        a = i.axis,
  		  x1 = i.offset.left,
  		  x2 = x1 + i.size.width,
  		  y1 = i.position.top,
  		  y2 = y1 + i.size.height,
  		  wd = i.sizeDiff.width,
  		  hd = i.sizeDiff.height;

  		for (var n = i.guideElements.length - 1; n >= 0; n--){

  			var l = i.guideElements[n].left,
  		    r = l + i.guideElements[n].width,
  		    t = i.guideElements[n].top,
  		    b = t + i.guideElements[n].height,
  		    ip = i.guideElements[n].inner,
  		    lp = l - p,
  		    rp = r + p,
  		    tp = t - p,
  		    bp = b + p,
  		    li = l + p,
  		    ri = r - p,
  		    ti = t + p,
  		    bi = b - p,
  		    cv = l + ((i.guideElements[n].width - ui.size.width) / 2),
  		    ch = t + ((i.guideElements[n].height - ui.size.height) / 2),
    		  xc = l + (i.guideElements[n].width / 2),
    		  yc = t + (i.guideElements[n].height / 2);

        if (a.indexOf('n') > -1) {

     			if (t - d < y1 && t + d > y1) { //Top SNAP ;)
  
            i.position.top = t;
            i.size.height = (y2 - t);
  
            if (g) drawGuide(l, x2, x1, r, t, c1, 0, s);
          } else if (p > 0 && ip && ti - d < y1 && ti + d > y1) {
  
            i.position.top = ti;
            i.size.height = (y2 - ti);
  
            if (g) drawGuide(l, x2, x1, r, ti, c4, 0, s);
          }

          if (b - d < y1 && b + d > y1) { //Bottom SNAP ;)
  
            i.position.top = b;
            i.size.height = (y2 - b);
  
            if (g) drawGuide(l, x2, x1, r, b - 1, c1, 0, s);
          } else if (p > 0 && !ip && bp - d < y1 && bp + d > y1) {
  
            i.position.top = bp;
            i.size.height = (y2 - bp);
  
            if (g) drawGuide(l, x2, x1, r, bp - 1, c2, 0, s);
          }
        }
  
        if (a.indexOf('w') > -1) {

          if (l - d < x1 && l + d > x1) { //Left SNAP ;)
  
            i.offset.left = l;
            i.size.width = (x2 - l);
  
            if (g) drawGuide(t, y2, y1, b, l, c1, 1, s);
          } else if (p > 0 && ip && li - d < x1 && li + d > x1) {
  
            i.offset.left = lp;
            i.size.width = (x2 - lp);
  
            if (g) drawGuide(t, y2, y1, b, li, c4, 1, s);
          }

          if (r - d < x1 && r + d > x1) { //Right SNAP ;)
  
            i.offset.left = r;
            i.size.width = (x2 - r);
  
            if (g) drawGuide(t, y2, y1, b, r - 1, c1, 1, s);
          } else if (p > 0 && !ip && rp - d < x1 && rp + d > x1) {
  
            i.offset.left = rp;
            i.size.width = (x2 - rp);
  
            if (g) drawGuide(t, y2, y1, b, rp - 1, c2, 1, s);
          }
        }
  
        if (a.indexOf('s') > -1) {

          if (t - d < y2 && t + d > y2) { //Top SNAP ;)
  
            i.size.height = (t - y1) - hd;
  
            if (g) drawGuide(l, x2, x1, r, t, c1, 0, s);
          } else if (p > 0 && !ip && tp - d < y2 && tp + d > y2) {
  
            i.size.height = (tp - y1) - hd;
  
            if (g) drawGuide(l, x2, x1, r, tp, c2, 0, s);
          }

          if (b - d < y2 && b + d > y2) { //Bottom SNAP ;)
  
            i.size.height = (b - y1) - hd;
  
            if (g) drawGuide(l, x2, x1, r, b - 1, c1, 0, s);
          } else if (p > 0 && ip && bi - d < y2 && bi + d > y2) {
  
            i.size.height = (bi - y1) - hd;
  
            if (g) drawGuide(l, x2, x1, r, bi - 1, c4, 0, s);
          }
        }
  
        if (a.indexOf('e') > -1) {

          if (l - d < x2 && l + d > x2) { //Left SNAP ;)
  
            i.size.width = (l - x1) - wd;
  
            if (g) drawGuide(t, y2, y1, b, l, c1, 1, s);
          } else if (p > 0 && !ip && lp - d < x2 && lp + d > x2) {
  
            i.size.width = (lp - x1) - wd;
  
            if (g) drawGuide(t, y2, y1, b, lp, c2, 1, s);
          }

          if (r - d < x2 && r + d > x2) { //Right SNAP ;)
  
            i.size.width = (r - x1) - wd;
  
            if (g) drawGuide(t, y2, y1, b, r - 1, c1, 1, s);
          } else if (p > 0 && ip && ri - d < x2 && ri + d > x2) {
  
            i.size.width = (ri - x1) - wd;
  
            if (g) drawGuide(t, y2, y1, b, ri - 1, c4, 1, s);
          }
        }
  		}
  	}
  });

  var drawGuide = function (n1, n2, n3, n4, n5, c, b, s) {

  	var i = Math.floor(Math.random()*10);

  	$("body").append('<div id="snapGuide_' + i +'"></div>');

  	if (b == 0) {

      var l = n1, w = (n2 - n1), h = 1, t = n5, d = 'border-top';

      if (n3 < n1) {

        l = n3;
        w = (n4 - n3);
      }
  	} else {

      var t = n1, h = (n2 - n1), w = 1, l = n5, d = 'border-left';

      if (n3 < n1) {

        t = n3;
        h = (n4 - n3);
      }
    }

  	$("#snapGuide_" + i).css(d, '1px ' + s +' ' + c).css({
  	  'height' : h + 'px',
  	  'z-index' : '999999',
  	  'position' : 'absolute',
  	  'display' : 'block',
  	  'top' : t + 'px',
  	  'left' : l + 'px',
  	  'width' : w + 'px'
  	}).fadeOut("slow").empty();
  };
})();

