/*!
 * jQuery UI Resizable @VERSION
 *
 * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Resizables
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function( $, undefined ) {

$.widget("ui.resizable", $.ui.mouse, {
	version: "@VERSION",
	widgetEventPrefix: "resize",
	options: {
		alsoResize: false,
		animate: false,
		animateDuration: "slow",
		animateEasing: "swing",
		aspectRatio: false,
		autoHide: false,
		containment: false,
		ghost: false,
		grid: false,
		handles: "e,s,se",
		helper: false,
		maxHeight: null,
		maxWidth: null,
		minHeight: 10,
		minWidth: 10,
		zIndex: 1000
	},
	_create: function() {

		var that = this, o = this.options;
		this.element.addClass("ui-resizable");

		$.extend(this, {
			_aspectRatio: !!(o.aspectRatio),
			aspectRatio: o.aspectRatio,
			originalElement: this.element,
			_proportionallyResizeElements: [],
			_helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
		});

		//Wrap the element if it cannot hold child nodes
		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {

			//Create a wrapper element and set the wrapper to the new current internal element
			this.element.wrap(
				$('

').css({
					position: this.element.css('position'),
					width: this.element.outerWidth(),
					height: this.element.outerHeight(),
					top: this.element.css('top'),
					left: this.element.css('left')
				})
			);

			//Overwrite the original this.element
			this.element = this.element.parent().data(
				"resizable", this.element.data('resizable')
			);

			this.elementIsWrapper = true;

			//Move margins to the wrapper
			this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
			this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});

			//Prevent Safari textarea resize
			this.originalResizeStyle = this.originalElement.css('resize');
			this.originalElement.css('resize', 'none');

			//Push the actual element to our proportionallyResize internal array
			this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));

			// avoid IE jump (hard set the margin)
			this.originalElement.css({ margin: this.originalElement.css('margin') });

			// fix handlers offset
			this._proportionallyResize();

		}

		this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
		if(this.handles.constructor == String) {

			if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
			var n = this.handles.split(","); this.handles = {};

			for(var i = 0; i < n.length; i++) {

				var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
				var axis = $('

');

				// Apply zIndex to all handles - see #7960
				axis.css({ zIndex: o.zIndex });

				//TODO : What's going on here?
				if ('se' == handle) {
					axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
				};

				//Insert into internal handles object and append to element
				this.handles[handle] = '.ui-resizable-'+handle;
				this.element.append(axis);
			}

		}

		this._renderAxis = function(target) {

			target = target || this.element;

			for(var i in this.handles) {

				if(this.handles[i].constructor == String)
					this.handles[i] = $(this.handles[i], this.element).show();

				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {

					var axis = $(this.handles[i], this.element), padWrapper = 0;

					//Checking the correct pad and border
					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();

					//The padding type i have to apply...
					var padPos = [ 'padding',
						/ne|nw|n/.test(i) ? 'Top' :
						/se|sw|s/.test(i) ? 'Bottom' :
						/^e$/.test(i) ? 'Right' : 'Left' ].join("");

					target.css(padPos, padWrapper);

					this._proportionallyResize();

				}

				//TODO: What's that good for? There's not anything to be executed left
				if(!$(this.handles[i]).length)
					continue;

			}
		};

		//TODO: make renderAxis a prototype function
		this._renderAxis(this.element);

		this._handles = $('.ui-resizable-handle', this.element)
			.disableSelection();

		//Matching axis name
		this._handles.mouseover(function() {
			if (!that.resizing) {
				if (this.className)
					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
				//Axis, default = se
				that.axis = axis && axis[1] ? axis[1] : 'se';
			}
		});

		//If we want to auto hide the elements
		if (o.autoHide) {
			this._handles.hide();
			$(this.element)
				.addClass("ui-resizable-autohide")
				.mouseenter(function() {
					if (o.disabled) return;
					$(this).removeClass("ui-resizable-autohide");
					that._handles.show();
				})
				.mouseleave(function(){
					if (o.disabled) return;
					if (!that.resizing) {
						$(this).addClass("ui-resizable-autohide");
						that._handles.hide();
					}
				});
		}

		//Initialize the mouse interaction
		this._mouseInit();

	},

	_destroy: function() {

		this._mouseDestroy();

		var _destroy = function(exp) {
			$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
				.removeData("resizable").removeData("ui-resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
		};

		//TODO: Unwrap at same DOM position
		if (this.elementIsWrapper) {
			_destroy(this.element);
			var wrapper = this.element;
			wrapper.after(
				this.originalElement.css({
					position: wrapper.css('position'),
					width: wrapper.outerWidth(),
					height: wrapper.outerHeight(),
					top: wrapper.css('top'),
					left: wrapper.css('left')
				})
			).remove();
		}

		this.originalElement.css('resize', this.originalResizeStyle);
		_destroy(this.originalElement);

		return this;
	},

	_mouseCapture: function(event) {
		var handle = false;
		for (var i in this.handles) {
			if ($(this.handles[i])[0] == event.target) {
				handle = true;
			}
		}

		return !this.options.disabled && handle;
	},

	_mouseStart: function(event) {

		var o = this.options, iniPos = this.element.position(), el = this.element;

		this.resizing = true;
		this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };

		// bugfix for http://dev.jquery.com/ticket/1749
		if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
			el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
		}

		this._renderProxy();

		var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));

		if (o.containment) {
			curleft += $(o.containment).scrollLeft() || 0;
			curtop += $(o.containment).scrollTop() || 0;
		}

		//Store needed variables
		this.offset = this.helper.offset();
		this.position = { left: curleft, top: curtop };
		this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
		this.originalPosition = { left: curleft, top: curtop };
		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
		this.originalMousePosition = { left: event.pageX, top: event.pageY };

		//Aspect Ratio
		this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);

		var cursor = $('.ui-resizable-' + this.axis).css('cursor');
		$('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);

		el.addClass("ui-resizable-resizing");
		this._propagate("start", event);
		return true;
	},

	_mouseDrag: function(event) {

		//Increase performance, avoid regex
		var el = this.helper, o = this.options, props = {},
			that = this, smp = this.originalMousePosition, a = this.axis;

		var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
		var trigger = this._change[a];
		if (!trigger) return false;

		// Calculate the attrs that will be change
		var data = trigger.apply(this, [event, dx, dy]);

		// Put this in the mouseDrag handler since the user can start pressing shift while resizing
		this._updateVirtualBoundaries(event.shiftKey);
		if (this._aspectRatio || event.shiftKey)
			data = this._updateRatio(data, event);

		data = this._respectSize(data, event);

		// plugins callbacks need to be called first
		this._propagate("resize", event);

		el.css({
			top: this.position.top + "px", left: this.position.left + "px",
			width: this.size.width + "px", height: this.size.height + "px"
		});

		if (!this._helper && this._proportionallyResizeElements.length)
			this._proportionallyResize();

		this._updateCache(data);

		// calling the user callback at the end
		this._trigger('resize', event, this.ui());

		return false;
	},

	_mouseStop: function(event) {

		this.resizing = false;
		var o = this.options, that = this;

		if(this._helper) {
			var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
				soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : that.sizeDiff.height,
				soffsetw = ista ? 0 : that.sizeDiff.width;

			var s = { width: (that.helper.width()  - soffsetw), height: (that.helper.height() - soffseth) },
				left = (parseInt(that.element.css('left'), 10) + (that.position.left - that.originalPosition.left)) || null,
				top = (parseInt(that.element.css('top'), 10) + (that.position.top - that.originalPosition.top)) || null;

			if (!o.animate)
				this.element.css($.extend(s, { top: top, left: left }));

			that.helper.height(that.size.height);
			that.helper.width(that.size.width);

			if (this._helper && !o.animate) this._proportionallyResize();
		}

		$('body').css('cursor', 'auto');

		this.element.removeClass("ui-resizable-resizing");

		this._propagate("stop", event);

		if (this._helper) this.helper.remove();
		return false;

	},

	_updateVirtualBoundaries: function(forceAspectRatio) {
		var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b;

		b = {
			minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
			maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
			minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
			maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
		};

		if(this._aspectRatio || forceAspectRatio) {
			// We want to create an enclosing box whose aspect ration is the requested one
			// First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
			pMinWidth = b.minHeight * this.aspectRatio;
			pMinHeight = b.minWidth / this.aspectRatio;
			pMaxWidth = b.maxHeight * this.aspectRatio;
			pMaxHeight = b.maxWidth / this.aspectRatio;

			if(pMinWidth > b.minWidth) b.minWidth = pMinWidth;
			if(pMinHeight > b.minHeight) b.minHeight = pMinHeight;
			if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth;
			if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight;
		}
		this._vBoundaries = b;
	},

	_updateCache: function(data) {
		var o = this.options;
		this.offset = this.helper.offset();
		if (isNumber(data.left)) this.position.left = data.left;
		if (isNumber(data.top)) this.position.top = data.top;
		if (isNumber(data.height)) this.size.height = data.height;
		if (isNumber(data.width)) this.size.width = data.width;
	},

	_updateRatio: function(data, event) {

		var o = this.options, cpos = this.position, csize = this.size, a = this.axis;

		if (isNumber(data.height)) data.width = (data.height * this.aspectRatio);
		else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio);

		if (a == 'sw') {
			data.left = cpos.left + (csize.width - data.width);
			data.top = null;
		}
		if (a == 'nw') {
			data.top = cpos.top + (csize.height - data.height);
			data.left = cpos.left + (csize.width - data.width);
		}

		return data;
	},

	_respectSize: function(data, event) {

		var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
				ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
					isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);

		if (isminw) data.width = o.minWidth;
		if (isminh) data.height = o.minHeight;
		if (ismaxw) data.width = o.maxWidth;
		if (ismaxh) data.height = o.maxHeight;

		var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
		var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);

		if (isminw && cw) data.left = dw - o.minWidth;
		if (ismaxw && cw) data.left = dw - o.maxWidth;
		if (isminh && ch)	data.top = dh - o.minHeight;
		if (ismaxh && ch)	data.top = dh - o.maxHeight;

		// fixing jump error on top/left - bug #2330
		var isNotwh = !data.width && !data.height;
		if (isNotwh && !data.left && data.top) data.top = null;
		else if (isNotwh && !data.top && data.left) data.left = null;

		return data;
	},

	_proportionallyResize: function() {

		var o = this.options;
		if (!this._proportionallyResizeElements.length) return;
		var element = this.helper || this.element;

		for (var i=0; i < this._proportionallyResizeElements.length; i++) {

			var prel = this._proportionallyResizeElements[i];

			if (!this.borderDif) {
				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];

				this.borderDif = $.map(b, function(v, i) {
					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
					return border + padding;
				});
			}

			if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
				continue;

			prel.css({
				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
			});

		};

	},

	_renderProxy: function() {

		var el = this.element, o = this.options;
		this.elementOffset = el.offset();

		if(this._helper) {

			this.helper = this.helper || $('

');

			// fix ie6 offset TODO: This seems broken
			var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
			pxyoffset = ( ie6 ? 2 : -1 );

			this.helper.addClass(this._helper).css({
				width: this.element.outerWidth() + pxyoffset,
				height: this.element.outerHeight() + pxyoffset,
				position: 'absolute',
				left: this.elementOffset.left - ie6offset +'px',
				top: this.elementOffset.top - ie6offset +'px',
				zIndex: ++o.zIndex //TODO: Don't modify option
			});

			this.helper
				.appendTo("body")
				.disableSelection();

		} else {
			this.helper = this.element;
		}

	},

	_change: {
		e: function(event, dx, dy) {
			return { width: this.originalSize.width + dx };
		},
		w: function(event, dx, dy) {
			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
			return { left: sp.left + dx, width: cs.width - dx };
		},
		n: function(event, dx, dy) {
			var o = this.options, cs = this.originalSize, sp = this.originalPosition;
			return { top: sp.top + dy, height: cs.height - dy };
		},
		s: function(event, dx, dy) {
			return { height: this.originalSize.height + dy };
		},
		se: function(event, dx, dy) {
			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
		},
		sw: function(event, dx, dy) {
			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
		},
		ne: function(event, dx, dy) {
			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
		},
		nw: function(event, dx, dy) {
			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
		}
	},

	_propagate: function(n, event) {
		$.ui.plugin.call(this, n, [event, this.ui()]);
		(n != "resize" && this._trigger(n, event, this.ui()));
	},

	plugins: {},

	ui: function() {
		return {
			originalElement: this.originalElement,
			element: this.element,
			helper: this.helper,
			position: this.position,
			size: this.size,
			originalSize: this.originalSize,
			originalPosition: this.originalPosition
		};
	}

});

/*
 * Resizable Extensions
 */

$.ui.plugin.add("resizable", "alsoResize", {

	start: function (event, ui) {
		var that = $(this).data("resizable"), o = that.options;

		var _store = function (exp) {
			$(exp).each(function() {
				var el = $(this);
				el.data("resizable-alsoresize", {
					width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
					left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10)
				});
			});
		};

		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
		}else{
			_store(o.alsoResize);
		}
	},

	resize: function (event, ui) {
		var that = $(this).data("resizable"), o = that.options, os = that.originalSize, op = that.originalPosition;

		var delta = {
			height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0,
			top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0
		},

		_alsoResize = function (exp, c) {
			$(exp).each(function() {
				var el = $(this), start = $(this).data("resizable-alsoresize"), style = {},
					css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];

				$.each(css, function (i, prop) {
					var sum = (start[prop]||0) + (delta[prop]||0);
					if (sum && sum >= 0)
						style[prop] = sum || null;
				});

				el.css(style);
			});
		};

		if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
		}else{
			_alsoResize(o.alsoResize);
		}
	},

	stop: function (event, ui) {
		$(this).removeData("resizable-alsoresize");
	}
});

$.ui.plugin.add("resizable", "animate", {

	stop: function(event, ui) {
		var that = $(this).data("resizable"), o = that.options;

		var pr = that._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
					soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : that.sizeDiff.height,
						soffsetw = ista ? 0 : that.sizeDiff.width;

		var style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
					left = (parseInt(that.element.css('left'), 10) + (that.position.left - that.originalPosition.left)) || null,
						top = (parseInt(that.element.css('top'), 10) + (that.position.top - that.originalPosition.top)) || null;

		that.element.animate(
			$.extend(style, top && left ? { top: top, left: left } : {}), {
				duration: o.animateDuration,
				easing: o.animateEasing,
				step: function() {

					var data = {
						width: parseInt(that.element.css('width'), 10),
						height: parseInt(that.element.css('height'), 10),
						top: parseInt(that.element.css('top'), 10),
						left: parseInt(that.element.css('left'), 10)
					};

					if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });

					// propagating resize, and updating values for each animation step
					that._updateCache(data);
					that._propagate("resize", event);

				}
			}
		);
	}

});

$.ui.plugin.add("resizable", "containment", {

	start: function(event, ui) {
		var that = $(this).data("resizable"), o = that.options, el = that.element;
		var oc = o.containment,	ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
		if (!ce) return;

		that.containerElement = $(ce);

		if (/document/.test(oc) || oc == document) {
			that.containerOffset = { left: 0, top: 0 };
			that.containerPosition = { left: 0, top: 0 };

			that.parentData = {
				element: $(document), left: 0, top: 0,
				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
			};
		}

		// i'm a node, so compute top, left, right, bottom
		else {
			var element = $(ce), p = [];
			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });

			that.containerOffset = element.offset();
			that.containerPosition = element.position();
			that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };

			var co = that.containerOffset, ch = that.containerSize.height,	cw = that.containerSize.width,
						width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);

			that.parentData = {
				element: ce, left: co.left, top: co.top, width: width, height: height
			};
		}
	},

	resize: function(event, ui) {
		var that = $(this).data("resizable"), o = that.options,
				ps = that.containerSize, co = that.containerOffset, cs = that.size, cp = that.position,
				pRatio = that._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = that.containerElement;

		if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;

		if (cp.left < (that._helper ? co.left : 0)) {
			that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left));
			if (pRatio) that.size.height = that.size.width / that.aspectRatio;
			that.position.left = o.helper ? co.left : 0;
		}

		if (cp.top < (that._helper ? co.top : 0)) {
			that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top);
			if (pRatio) that.size.width = that.size.height * that.aspectRatio;
			that.position.top = that._helper ? co.top : 0;
		}

		that.offset.left = that.parentData.left+that.position.left;
		that.offset.top = that.parentData.top+that.position.top;

		var woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width ),
					hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height );

		var isParent = that.containerElement.get(0) == that.element.parent().get(0),
			isOffsetRelative = /relative|absolute/.test(that.containerElement.css('position'));

		if(isParent && isOffsetRelative) woset -= that.parentData.left;

		if (woset + that.size.width >= that.parentData.width) {
			that.size.width = that.parentData.width - woset;
			if (pRatio) that.size.height = that.size.width / that.aspectRatio;
		}

		if (hoset + that.size.height >= that.parentData.height) {
			that.size.height = that.parentData.height - hoset;
			if (pRatio) that.size.width = that.size.height * that.aspectRatio;
		}
	},

	stop: function(event, ui){
		var that = $(this).data("resizable"), o = that.options, cp = that.position,
				co = that.containerOffset, cop = that.containerPosition, ce = that.containerElement;

		var helper = $(that.helper), ho = helper.offset(), w = helper.outerWidth() - that.sizeDiff.width, h = helper.outerHeight() - that.sizeDiff.height;

		if (that._helper && !o.animate && (/relative/).test(ce.css('position')))
			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });

		if (that._helper && !o.animate && (/static/).test(ce.css('position')))
			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });

	}
});

$.ui.plugin.add("resizable", "ghost", {

	start: function(event, ui) {

		var that = $(this).data("resizable"), o = that.options, cs = that.size;

		that.ghost = that.originalElement.clone();
		that.ghost
			.css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
			.addClass('ui-resizable-ghost')
			.addClass(typeof o.ghost == 'string' ? o.ghost : '');

		that.ghost.appendTo(that.helper);

	},

	resize: function(event, ui){
		var that = $(this).data("resizable"), o = that.options;
		if (that.ghost) that.ghost.css({ position: 'relative', height: that.size.height, width: that.size.width });
	},

	stop: function(event, ui){
		var that = $(this).data("resizable"), o = that.options;
		if (that.ghost && that.helper) that.helper.get(0).removeChild(that.ghost.get(0));
	}

});

$.ui.plugin.add("resizable", "grid", {

	resize: function(event, ui) {
		var that = $(this).data("resizable"), o = that.options, cs = that.size, os = that.originalSize, op = that.originalPosition, a = that.axis, ratio = o._aspectRatio || event.shiftKey;
		o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
		var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);

		if (/^(se|s|e)$/.test(a)) {
			that.size.width = os.width + ox;
			that.size.height = os.height + oy;
		}
		else if (/^(ne)$/.test(a)) {
			that.size.width = os.width + ox;
			that.size.height = os.height + oy;
			that.position.top = op.top - oy;
		}
		else if (/^(sw)$/.test(a)) {
			that.size.width = os.width + ox;
			that.size.height = os.height + oy;
			that.position.left = op.left - ox;
		}
		else {
			that.size.width = os.width + ox;
			that.size.height = os.height + oy;
			that.position.top = op.top - oy;
			that.position.left = op.left - ox;
		}
	}

});

var num = function(v) {
	return parseInt(v, 10) || 0;
};

var isNumber = function(value) {
	return !isNaN(parseInt(value, 10));
};

})(jQuery);


"menu/type":          { "attribOption": ["context", "list", "toolbar"] },

"script/type":        { "attribOption": ["text/javascript", "text/ecmascript", "text/jscript", "text/livescript", "text/tcl", "text/x-javascript", "text/x-ecmascript",

"application/x-javascript", "application/x-ecmascript", "application/javascript", "application/ecmascript"] },

"style/type":         { "attribOption": ["text/css"] },

"input/type":         { "attribOption": ["button", "checkbox", "color", "date", "datetime", "datetime-local", "email", "file", "hidden", "image", "month",

"number", "password", "radio", "range", "reset", "search", "submit", "tel", "text", "time", "url", "week"] },

"application/x-javascript", "application/x-ecmascript", "application/javascript", "application/ecmascript",

open

open a file or url in the user's preferred application

# open

Open a file or url in the user's preferred application.

# Usage

```javascript
var open = require("open");
open("http://www.google.com");
```

`open` taks an optional argument specifying the program to be used to open the
file or URL.

```javascript
open("http://www.google.com", "firefox");
```

# Installation

    npm install open

# How it works

- on `win32` uses `start`
- on `darwin` uses `open`
- otherwise uses the `xdg-open` script from [freedesktop.org](http://portland.freedesktop.org/xdg-utils-1.0/xdg-open.html)

# Warning

The same care should be taken when calling open as if you were calling
[child_process.exec](http://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback)
directly. If it is an executable it will run in a new shell.


"attribOptions": ["auto", "inherit", "optimizeQuality", "optimizeSpeed"]

"attribOptions": ["application/ecmascript", "application/javascript", "application/x-ecmascript", "application/x-javascript", "text/ecmascript", "text/javascript", "text/jscript", "text/livescript", "text/tcl", "text/x-ecmascript", "text/x-javascript"]

keep keep keep keep replace keep keep keep keep keep

"attribOptions": ["application/ecmascript", "application/javascript", "application/x-ecmascript", "application/x-javascript", "text/ecmascript", "text/javascript", "text/jscript", "text/livescript", "text/tcl", "text/x-ecmascript", "text/x-javascript", "text/babel", "text/jsx"]

ab aa af sq am ar an hy as ay az ba eu bn dz bh bi br bg my be km ca zh co hr cs da nl en eo et fo fa fi fr fy gl gd gv ka de el kl gn gu ht ha he hi hu is io id ia ie iu ik ga it ja jv kn ks kk rw ky rn ko ku lo la lv li ln lt mk mg ms ml mt mi mr mo mn na ne no oc or om ps pl pt pa qu rm ro ru sz sm sg sa sr sh st tn sn ii sd si ss sk sl so es su sw sv tl tg ta tt te th bo ti to ts tr tk tw ug uk ur uz vi vo wa cy wo xh yi yo zu

alert alertdialog article application banner button checkbox columnheader combobox complementary contentinfo definition directory dialog document form grid gridcell group heading img link list listbox listitem log main marquee math menu menubar menuitem menuitemcheckbox menuitemradio navigation note option presentation progressbar radio radiogroup region row rowgroup rowheader scrollbar search separator slider spinbutton status tab tablist tabpanel textbox timer toolbar tooltip tree treegrid treeitem

text/html text/plain application/msword application/msexcel application/postscript application/x-zip-compressed application/pdf application/rtf video/x-msvideo video/quicktime video/x-mpeg2 audio/x-pn/realaudio audio/x-mpeg audio/x-waw audio/x-aiff audio/basic image/tiff image/jpeg image/gif image/x-png image/x-photo-cd image/x-MS-bmp image/x-rgb image/x-portable-pixmap image/x-portable-greymap image/x-portablebitmap

captions chapters descriptions metadata subtitles

screen tty tv projection handheld print aural braille embossed speech all width min-width max-width height min-height max-height device-width min-device-width max-device-width device-height min-device-height max-device-height orientation aspect-ratio min-aspect-ratio max-aspect-ratio device-aspect-ratio min-device-aspect-ratio max-device-aspect-ratio color min-color max-color color-index min-color-index max-color-index monochrome min-monochrome max-monochrome resolution min-resolution max-resolution scan grid

application-name author description generator keywords

alternate author bookmark help license next nofollow noreferrer prefetch prev search sidebar tag external

alternate author help icon license next pingback prefetch prev search sidebar stylesheet tag

allow-forms allow-same-origin allow-scripts allow-top-navigation

text/javascript text/ecmascript text/jscript text/livescript text/tcl text/x-javascript text/x-ecmascript application/x-javascript application/x-ecmascript application/javascript application/ecmascript

button checkbox color date datetime datetime-local email file hidden image month number password radio range reset search submit tel text time url week


<!DOCTYPE html>

	<meta charset="utf-8">
	<title>jQuery UI Resizable - Synchronous resize</title>
	<link rel="stylesheet" href="../../themes/base/jquery.ui.all.css">

	<link rel="stylesheet" href="../demos.css">

Resize

will also resize

Resize multiple elements simultaneously by clicking and dragging the sides of one.  Pass a shared selector into the alsoResize option.


function testMe() {
    console.log("this is a test");
}

function main() {
    testMe();
}


"attribOptions": ["always", "never", "whenNotActive"]

keep keep keep keep replace keep keep keep

after-edge alphabetic auto baseline before-edge central hanging ideographic inherit mathematical middle text-after-edge text-before-edge

auto inherit optimizeQuality optimizeSpeed

application/ecmascript application/javascript application/x-ecmascript application/x-javascript text/ecmascript text/javascript text/jscript text/livescript text/tcl text/x-ecmascript text/x-javascript

auto crosshair default e-resize help inherit move n-resize ne-resize nw-resize pointer s-resize se-resize sw-resize text w-resize wait

block compact inherit inline inline-table list-item marker none run-in table table-caption table-cell table-column table-column-group table-footer-group table-header-group table-row table-row-group

alphabetic auto central hanging ideographic inherit mathematical middle no-change reset-size text-after-edge text-before-edge use-script

hueRotate luminanceToAlpha matrix saturate

all condensed expanded extra-condensed extra-expanded inherit narrower normal semi-condensed semi-expanded ultra-condensed ultra-expanded wider

matrix() rotate() scale() skewX() skewY() translate()

BackgroundAlpha BackgroundImage FillPaint SourceAlpha SourceGraphic StrokePaint

aa ab af am ar as ay az ba be bg bh bi bn bo br ca co cs cy da de dz el en eo es et eu fa fi fj fo fr fy ga gd gl gn gu ha hi hr hu hy ia ie ik in is it iw ja ji jw ka kk kl km kn ko ks ku ky la ln lo lt lv mg mi mk ml mn mo mr ms mt my na ne nl no oc om or pa pl ps pt qu rm rn ro ru rw sa sd sg sh si sk sl sm sn so sq sr ss st su sv sw ta te tg th ti tk tl tn to tr ts tt tw uk ur uz vi vo wo xh yo zh zu

all fill inherit none painted stroke visible visibleFill visiblePainted visibleStroke

meet none slice xMaxYMax xMaxYMid xMaxYMin xMidYMax xMidYMid xMidYMin xMinYMax xMinYMid xMinYMin

absolute-colorimetric auto perceptual relative-colorimetric saturation

auto crispEdges geometricPrecision inherit optimizeSpeed

blink inherit line-through none overline underline

auto geometricPrecision inherit optimizeLegibility optimizeSpeed


/*
 * Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, describe, it, expect, runs, spyOn */

define(function (require, exports, module) {
    'use strict';

    var MainViewFactory = require("view/MainViewFactory");

    describe("ViewFactory", function () {
        function createMockFactory() {
            return {
                canOpenFile: function (fullPath) {
                    return (fullPath === "blah");
                }
            };
        }
        it("should register a factory", function () {
            runs(function () {
                var factory = createMockFactory();
                spyOn(factory, "canOpenFile");
                MainViewFactory.registerViewFactory(factory);
                MainViewFactory.findSuitableFactoryForPath();
                expect(factory.canOpenFile).toHaveBeenCalled();
            });
        });
        it("should find a factory", function () {
            runs(function () {
                var factory = createMockFactory();

                MainViewFactory.registerViewFactory(factory);
                var result = MainViewFactory.findSuitableFactoryForPath("blah");

                expect(result).toBeTruthy();
            });
        });
        it("should not find a factory", function () {
            runs(function () {
                var factory = createMockFactory();
                MainViewFactory.registerViewFactory(factory);
                var result = MainViewFactory.findSuitableFactoryForPath("blahblah");
                expect(result).toBeFalsy();
            });
        });
    });
});


# buffer-crc32

[![Build Status](https://secure.travis-ci.org/brianloveswords/buffer-crc32.png?branch=master)](http://travis-ci.org/brianloveswords/buffer-crc32)

crc32 that works with binary data and fancy character sets, outputs
buffer, signed or unsigned data and has tests.

Derived from the sample CRC implementation in the PNG specification: http://www.w3.org/TR/PNG/#D-CRCAppendix

# install
```
npm install buffer-crc32
```

# example
```js
var crc32 = require('buffer-crc32');
// works with buffers
var buf = Buffer([0x00, 0x73, 0x75, 0x70, 0x20, 0x62, 0x72, 0x6f, 0x00])
crc32(buf) // -> <Buffer 94 5a ab 4a>

// has convenience methods for getting signed or unsigned ints
crc32.signed(buf) // -> -1805997238
crc32.unsigned(buf) // -> 2488970058

// will cast to buffer if given a string, so you can
// directly use foreign characters safely
crc32('自動販売機') // -> <Buffer cb 03 1a c5>

// and works in append mode too
var partialCrc = crc32('hey');
var partialCrc = crc32(' ', partialCrc);
var partialCrc = crc32('sup', partialCrc);
var partialCrc = crc32(' ', partialCrc);
var finalCrc = crc32('bros', partialCrc); // -> <Buffer 47 fa 55 70>
```

# tests
This was tested against the output of zlib's crc32 method. You can run
the tests with`npm test` (requires tap)

# see also
https://github.com/alexgorbatchev/node-crc, `crc.buffer.crc32` also
supports buffer inputs and return unsigned ints (thanks @tjholowaychuk).

# license
MIT/X11


// far were strings, so we spare us the trouble of allowing more complex mode values.

// Define SVG MIME type so an SVG language can be defined for SVG-specific code hints.

// Currently, SVG uses XML mode so it has generic XML syntax highlighting. This can

// be removed when SVG gets its own CodeMirror mode with SVG syntax highlighting.

keep keep keep replace replace keep keep keep keep keep


var buf = new Buffer([ 97, 98, 99, 100, 101, 102, 0 ]);

var binary = require('binary');
binary(buf)
    .word16ls('ab')
    .word32bu('cf')
    .word8('x')
    .tap(function (vars) {
        console.dir(vars);
    })
;


// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

var assert = require('assert');
var common = require('../common.js');
var fromList = require('../../lib/_stream_readable')._fromList;

// tiny node-tap lookalike.
var tests = [];
var count = 0;

function test(name, fn) {
  count++;
  tests.push([name, fn]);
}

function run() {
  var next = tests.shift();
  if (!next)
    return console.error('ok');

  var name = next[0];
  var fn = next[1];
  console.log('# %s', name);
  fn({
    same: assert.deepEqual,
    equal: assert.equal,
    end: function () {
      count--;
      run();
    }
  });
}

// ensure all tests have run
process.on("exit", function () {
  assert.equal(count, 0);
});

process.nextTick(run);

test('buffers', function(t) {
  // have a length
  var len = 16;
  var list = [ new Buffer('foog'),
               new Buffer('bark'),
               new Buffer('bazy'),
               new Buffer('kuel') ];

  // read more than the first element.
  var ret = fromList(6, { buffer: list, length: 16 });
  t.equal(ret.toString(), 'foogba');

  // read exactly the first element.
  ret = fromList(2, { buffer: list, length: 10 });
  t.equal(ret.toString(), 'rk');

  // read less than the first element.
  ret = fromList(2, { buffer: list, length: 8 });
  t.equal(ret.toString(), 'ba');

  // read more than we have.
  ret = fromList(100, { buffer: list, length: 6 });
  t.equal(ret.toString(), 'zykuel');

  // all consumed.
  t.same(list, []);

  t.end();
});

test('strings', function(t) {
  // have a length
  var len = 16;
  var list = [ 'foog',
               'bark',
               'bazy',
               'kuel' ];

  // read more than the first element.
  var ret = fromList(6, { buffer: list, length: 16, decoder: true });
  t.equal(ret, 'foogba');

  // read exactly the first element.
  ret = fromList(2, { buffer: list, length: 10, decoder: true });
  t.equal(ret, 'rk');

  // read less than the first element.
  ret = fromList(2, { buffer: list, length: 8, decoder: true });
  t.equal(ret, 'ba');

  // read more than we have.
  ret = fromList(100, { buffer: list, length: 6, decoder: true });
  t.equal(ret, 'zykuel');

  // all consumed.
  t.same(list, []);

  t.end();
});


if ((imgWidth + imagePos.left) < scaleDivRight) {

scaleDivRight = imgWidth + imagePos.left;

if ((imgHeight + imagePos.top) < scaleDivBottom) {

scaleDivBottom = imgHeight + imagePos.top;

/*
 * Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, $, window, Mustache */
define(function (require, exports, module) {
    "use strict";

    var DocumentManager     = require("document/DocumentManager"),
        EditorManager       = require("editor/EditorManager"),
        ImageHolderTemplate = require("text!htmlContent/image-holder.html"),
        PanelManager        = require("view/PanelManager"),
        ProjectManager      = require("project/ProjectManager"),
        Strings             = require("strings"),
        StringUtils         = require("utils/StringUtils"),
        FileSystem          = require("filesystem/FileSystem");

    var _naturalWidth = 0,
        _scale = 100,
        _scaleDivInfo = null;   // coordinates of hidden scale sticker

    /** Update the scale element, i.e. on resize
     *  @param {!string} currentWidth actual width of image in view
     */
    function _updateScale(currentWidth) {
        if (currentWidth < _naturalWidth) {
            _scale = currentWidth / _naturalWidth * 100;
            $("#img-scale").text(Math.floor(_scale) + "%")
                // Keep the position of the image scale div relative to the image.
                .css("left", $("#img-preview").position().left + 5)
                .show();
        } else {
            $("#img-scale").hide();
        }
    }

    /** handle editor resize event, i.e. update scale sticker */
    function _onEditorAreaResize() {
        _updateScale($("#img-preview").width());
    }

    /**
     * Update file name if necessary
     */
    function _onFileNameChange(e, oldName, newName) {
        var oldRelPath = ProjectManager.makeProjectRelativeIfPossible(oldName),
            currentPath = $("#img-path").text();

        if (currentPath === oldRelPath) {
            var newRelName = ProjectManager.makeProjectRelativeIfPossible(newName);
            $("#img-path").text(newRelName)
                .attr("title", newRelName);
        }
    }

    /**
     * Check mouse entering/exiting the scale sticker.
     * Hide it when entering and show it again when exiting.
     *
     * @param {number} offsetX mouse offset from the left of the previewing image
     * @param {number} offsetY mouseoffset from the top of the previewing image
     */
    function _handleMouseEnterOrExitScaleSticker(offsetX, offsetY) {
        var imagePos       = $("#img-preview").position(),
            scaleDivPos    = $("#img-scale").position(),
            imgWidth       = $("#img-preview").width(),
            imgHeight      = $("#img-preview").height(),
            scaleDivLeft,
            scaleDivTop,
            scaleDivRight,
            scaleDivBottom;

        if (_scaleDivInfo) {
            scaleDivLeft   = _scaleDivInfo.left;
            scaleDivTop    = _scaleDivInfo.top;
            scaleDivRight  = _scaleDivInfo.right;
            scaleDivBottom = _scaleDivInfo.bottom;
        } else {
            scaleDivLeft   = scaleDivPos.left;
            scaleDivTop    = scaleDivPos.top;
            scaleDivRight  = $("#img-scale").width() - scaleDivLeft;
            scaleDivBottom = $("#img-scale").height() - scaleDivTop;
        }

        if ((offsetX >= scaleDivLeft && offsetX <= scaleDivRight) &&
                (offsetY >= scaleDivTop && offsetY <= scaleDivBottom)) {
            // Handle mouse inside image scale div.
            // But hide it only if the pixel under mouse is also in the image.
            if (offsetX < (imagePos.left + imgWidth) &&
                    offsetY < (imagePos.top + imgHeight)) {
                // Remember image scale div coordinates before hiding it.
                _scaleDivInfo = {left: scaleDivPos.left,
                                 top: scaleDivPos.top,
                                 right: scaleDivRight,
                                 bottom: scaleDivBottom};
                $("#img-scale").hide();
            }
        } else if (_scaleDivInfo) {
            // See whether the cursor is no longer inside the hidden scale div.
            // If so, show it again.
            if ((offsetX < _scaleDivInfo.left || offsetX > _scaleDivInfo.right) ||
                    (offsetY < _scaleDivInfo.top || offsetY > _scaleDivInfo.bottom)) {
                _scaleDivInfo = null;
                $("#img-scale").show();
            }
        }
    }

    /**
     * Show image coordinates under the mouse cursor
     *
     * @param {MouseEvent} e mouse move event
     */
    function _showImageTip(e) {
        // Don't show image tip if _scale is close to zero.
        // since we won't have enough room to show tip anyway.
        if (Math.floor(_scale) === 0) {
            return;
        }

        var x                   = Math.floor(e.offsetX * 100 / _scale),
            y                   = Math.floor(e.offsetY * 100 / _scale),
            $target             = $(e.target),
            targetPos           = $target.position(),
            tipPos              = $("#img-tip").position(),
            imagePos            = $("#img-preview").position(),
            scaleDivPos         = $("#img-scale").position(),
            left                = e.offsetX + imagePos.left,
            top                 = e.offsetY + imagePos.top,
            width               = $("#img-preview").width(),
            height              = $("#img-preview").height(),
            windowWidth         = $(window).width(),
            fourDigitImageWidth = _naturalWidth.toString().length === 4,
            infoWidth1          = 112,    // info div width 96px + vertical toolbar width 16px
            infoWidth2          = 120,    // info div width 104px (for 4-digit image width) + vertical toolbar width 16px
            tipOffsetX          = 10,     // adjustment for info div left from x coordinate of cursor
            tipOffsetY          = -54,    // adjustment for info div top from y coordinate of cursor
            tipMinusOffsetX1    = -84,    // for less than 4-digit image width
            tipMinusOffsetX2    = -90;    // for 4-digit image width

        // Adjust left, top, x and y based on which element contains the cursor.
        // Return if the target element is no longer available as in the case of
        // a vertical guide that has its left equals to zero.
        if ($target.is(".img-guide")) {
            if ($target.is("#vert-guide")) {
                if (targetPos.left === 0) {
                    return;
                }
                left = targetPos.left;
                x = Math.floor(left * 100 / _scale);
            } else {
                if (targetPos.top === 0) {
                    return;
                }
                top = targetPos.top;
                y = Math.floor(top * 100 / _scale);
            }
        } else if (!$target.is("#img-preview")) {
            if ($target.is("#img-scale")) {
                left = scaleDivPos.left + e.offsetX;
                top = scaleDivPos.top + e.offsetY;
                x = Math.floor(left * 100 / _scale);
                y = Math.floor(top * 100 / _scale);
            } else if (tipPos.left && tipPos.top) {
                // Cursor must be inside the image tip.
                left = tipPos.left + e.offsetX;
                top = tipPos.top + e.offsetY;
                x = Math.floor(left * 100 / _scale);
                y = Math.floor(top * 100 / _scale);
            } else {
                return;
            }
        }

        _handleMouseEnterOrExitScaleSticker(left, top);
        if ($(e.target).is("#img-scale")) {
            // If we're in the scale sticker, then just return.
            return;
        }

        // Check whether to show the image tip on the left.
        if ((e.pageX + infoWidth1) > windowWidth ||
                (fourDigitImageWidth && (e.pageX + infoWidth2) > windowWidth)) {
            tipOffsetX = fourDigitImageWidth ? tipMinusOffsetX2 : tipMinusOffsetX1;
        }

        // For some reason we're getting -1 for e.offset when hovering over the very
        // first pixel of a scaled image. So adjust x to 0 if it is negative.
        if (x < 0) {
            x = 0;
        }

        $("#x-value").text(x + "px");
        $("#y-value").text(y + "px");

        $("#img-tip").css({
            left: left + tipOffsetX,
            top: top + tipOffsetY
        }).show();

        $("#horiz-guide").css({
            left: imagePos.left,
            top: top,
            width: width - 1
        }).show();

        $("#vert-guide").css({
            left: left,
            top: imagePos.top,
            height: height - 1
        }).show();
    }

    /**
     * Show image coordinates under the mouse cursor
     *
     * @param {MouseEvent} e mouse leave event
     */
    function _hideImageTip(e) {
        var $target   = $(e.target),
            targetPos = $target.position(),
            imagePos  = $("#img-preview").position(),
            right     = imagePos.left + $("#img-preview").width(),
            bottom    = imagePos.top + $("#img-preview").height(),
            offsetX   = e.offsetX,
            offsetY   = e.offsetY;

        if ($target.is(".img-guide")) {
            offsetX = targetPos.left + offsetX;
            offsetY = targetPos.top + offsetY;
        }

        // Hide image tip and guides only if the cursor is outside of the image.
        if (offsetX < imagePos.left || offsetX >= right ||
                offsetY < imagePos.top || offsetY >= bottom) {
            $("#img-tip").hide();
            $(".img-guide").hide();
//            $("#img-scale").show();
        }
    }

    /**
     * creates a DOM node to place in the editor-holder
     * in order to display an image.
     * @param {!string} fullPath  path to image file
     * @return {JQuery}
     *
     */
    function getCustomViewHolder(fullPath) {
        return $(Mustache.render(ImageHolderTemplate, {fullPath: fullPath}));
    }

    /**
     *
     */
    function _removeListeners() {
        $(PanelManager).off("editorAreaResize", _onEditorAreaResize);
        $(DocumentManager).off("fileNameChange", _onFileNameChange);
        $("#img").off("mousemove", "#img-preview, #img-scale, #img-tip, .img-guide", _showImageTip)
                 .off("mouseleave", "#img-preview, #img-scale, #img-tip, .img-guide", _hideImageTip);
    }

    /**
     * Perform decorations on the view that require loading the image in the browser,
     * i.e. getting actual and natural width and height andplacing the scale sticker
     * @param {!string} fullPath path to the image file
     */
    function render(fullPath) {
        var relPath = ProjectManager.makeProjectRelativeIfPossible(fullPath);

        _scale = 100;   // initialize to 100
        $("#img-path").text(relPath)
                .attr("title", relPath);
        $("#img-preview").on("load", function () {
            // add dimensions and size
            _naturalWidth = this.naturalWidth;
            var dimensionString = _naturalWidth + " × " + this.naturalHeight + " " + Strings.UNIT_PIXELS;
            // get image size
            var file = FileSystem.getFileForPath(fullPath);
            file.stat(function (err, stat) {
                if (err) {
                    $("#img-data").html(dimensionString);
                } else {
                    var sizeString = "";
                    if (stat.size) {
                        sizeString = " — " + StringUtils.prettyPrintBytes(stat.size, 2);
                    }
                    var dimensionAndSize = dimensionString + sizeString;
                    $("#img-data").html(dimensionAndSize)
                        .attr("title", dimensionAndSize
                                        .replace("×", "x")
                                        .replace("—", "-"));
                }
            });
            $("#image-holder").show();
            // listen to resize to  update the scale sticker
            $(PanelManager).on("editorAreaResize", _onEditorAreaResize);
            // listen to removal to stop listening to resize events
            $(EditorManager).on("removeCustomViewer", _removeListeners);
            $(DocumentManager).on("fileNameChange", _onFileNameChange);

            $("#img-tip").hide();
            $(".img-guide").hide();
            $("#img").on("mousemove", "#img-preview, #img-scale, #img-tip, .img-guide", _showImageTip)
                     .on("mouseleave", "#img-preview, #img-scale, #img-tip, .img-guide", _hideImageTip);

            _updateScale($(this).width());
        });
    }

    exports.getCustomViewHolder = getCustomViewHolder;
    exports.render              = render;
});


exports['rfc1867'] =
  { boundary: 'AaB03x',
    raw:
      '--AaB03x\r\n'+
      'content-disposition: form-data; name="field1"\r\n'+
      '\r\n'+
      'Joe Blow\r\nalmost tricked you!\r\n'+
      '--AaB03x\r\n'+
      'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+
      'Content-Type: text/plain\r\n'+
      '\r\n'+
      '... contents of file1.txt ...\r\r\n'+
      '--AaB03x--\r\n',
    parts:
    [ { headers: {
          'content-disposition': 'form-data; name="field1"',
        },
        data: 'Joe Blow\r\nalmost tricked you!',
      },
      { headers: {
          'content-disposition': 'form-data; name="pics"; filename="file1.txt"',
          'Content-Type': 'text/plain',
        },
        data: '... contents of file1.txt ...\r',
      }
    ]
  };

exports['noTrailing\r\n'] =
  { boundary: 'AaB03x',
    raw:
      '--AaB03x\r\n'+
      'content-disposition: form-data; name="field1"\r\n'+
      '\r\n'+
      'Joe Blow\r\nalmost tricked you!\r\n'+
      '--AaB03x\r\n'+
      'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+
      'Content-Type: text/plain\r\n'+
      '\r\n'+
      '... contents of file1.txt ...\r\r\n'+
      '--AaB03x--',
    parts:
    [ { headers: {
          'content-disposition': 'form-data; name="field1"',
        },
        data: 'Joe Blow\r\nalmost tricked you!',
      },
      { headers: {
          'content-disposition': 'form-data; name="pics"; filename="file1.txt"',
          'Content-Type': 'text/plain',
        },
        data: '... contents of file1.txt ...\r',
      }
    ]
  };

exports['emptyHeader'] =
  { boundary: 'AaB03x',
    raw:
      '--AaB03x\r\n'+
      'content-disposition: form-data; name="field1"\r\n'+
      ': foo\r\n'+
      '\r\n'+
      'Joe Blow\r\nalmost tricked you!\r\n'+
      '--AaB03x\r\n'+
      'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+
      'Content-Type: text/plain\r\n'+
      '\r\n'+
      '... contents of file1.txt ...\r\r\n'+
      '--AaB03x--\r\n',
    expectError: true,
  };


TestHelpers.commonWidgetTests( "autocomplete", {
	defaults: {
		appendTo: "body",
		autoFocus: false,
		delay: 300,
		disabled: false,
		messages: {
			noResults: "No search results.",
			results: $.ui.autocomplete.prototype.options.messages.results
		},
		minLength: 1,
		position: {
			my: "left top",
			at: "left bottom",
			collision: "none"
		},
		source: null,

		// callbacks
		change: null,
		close: null,
		create: null,
		focus: null,
		open: null,
		response: null,
		search: null,
		select: null
	}
});


scaleDivRight  = $("#img-scale").width() - scaleDivLeft;

scaleDivBottom = $("#img-scale").height() - scaleDivTop;

keep keep keep replace replace keep keep

scaleDivRight  = $("#img-scale").width() + scaleDivLeft;

scaleDivBottom = $("#img-scale").height() + scaleDivTop;

/*
 * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*
 * This file first imports all of the shared LESS/CSS, and then defines
 * version-specific layout (e.g. layout for the App shell, or layout for
 * the In-Browser version on Firefox).
 *
 * Going forward, we may have different versions of this file for different
 * Versions (e.g. App, In-Browser, etc.)
 *
 * Anything that is general/reusable should be pushed up into a LESS file
 * in the "styles" directory. See "brackets_shared.less" for the organization
 *
 * Date: @DATE
 */

/* IMPORTANT: importing brackets_shared should be the first step in this file
 * This is so that imported CSS files (NOT LESS files) end up in the
 * right place
 */
@import "brackets_shared.less";

/* Overall layout */

html, body {
    height: 100%;
    overflow: hidden;

    /* Turn off selection for UI elements */
    .user-select(none);

    /* And make sure we get a pointer cursor even over text */
    cursor: default;

    /* Turn off subpixel antialiasing on Mac since it flickers during animations. */
    -webkit-font-smoothing: antialiased;

    /* This is a hack to avoid flicker when animations (like inline editors) that use the GPU complete.
       It seems that we have to put it here rather than on the animated element in order to prevent the
       entire window from flashing.
       See: http://stackoverflow.com/questions/3461441/prevent-flicker-on-webkit-transition-of-webkit-transform
    */
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
}

.resizing-container {
    position: absolute;
    top: 0;
    width: 100%;
    height: 100%;
    z-index: @z-index-brackets-panel-resizer;

    &.horz-resizing {
        cursor: col-resize;
    }

    &.vert-resizing {
        cursor: row-resize;
    }
}

a, img {
    -webkit-user-drag: none;
}

.main-view {
    background: @background-color-3; // to keep the theme background consistent
    height: 100%;

    .sidebar {
        height: 100%;
        .vbox;
        width: @sidebar-width;  // changed dynamically via Resizer
        position: absolute;
        left: 0;
        top: 0;
    }

    .content {
        height: 100%;
        position: absolute;
        padding: 0;
        top: 0;
        left: @sidebar-width;  // changed dynamically via Resizer
        right: @main-toolbar-width;
    }
}

#titlebar, .modal-bar {
    border-bottom: 1px solid @tc-gray-panel-border;
    box-shadow: @tc-small-shadow-bottom;

    // Make sure the bottom box-shadow goes above the editor (position: relative needed to start a new stacking group)
    position: relative;
    z-index: @z-index-brackets-toolbar;
}

.busyCursor {
    cursor: wait !important;
}

#status-bar {
    position: relative;
    background: #fff;
    border-top: 1px solid rgba(0, 0, 0, 0.1);
    box-sizing: border-box;
    color: @tc-text;
    font-family: @sansFontFamily;
    font-size: 11px;
    line-height: 25px;
    height: 26px;
    overflow: hidden;
}

#status-info {
    color: @tc-text;
    left: 10px;
    position: absolute;
    white-space: nowrap;

    div {
        display: inline;
    }
}

#status-file {
    color: #999;
}

#status-indicators {
    background: #fff;
    color: @tc-text;
    position: absolute;
    right: 0;
    text-align: right;
    white-space: nowrap;

    > div {
        border-left: 1px solid rgba(0, 0, 0, 0.1);
        float: right;
        padding: 0 10px;
    }
    .spinner {  // spinner is tiny & usually invisible; reduce margin so gap is less glaring
        border: none;
        margin: 6px 10px;
        padding: 0;
    }

    #status-language {
        border-right: 1px solid rgba(0, 0, 0, 0.1);
    }
}

@-webkit-keyframes spinner-sprites-12 {
      0% { background-position:    0px 0px; }
    100% { background-position: -120px 0px; }
}
@-webkit-keyframes spinner-sprites-36 {
      0% { background-position:    0px 0px; }
    100% { background-position: -360px 0px; }
}

#status-indent > * {
    display: inline-block;
}

#status-indent > *.hidden {
    display: none;
}

#indent-type, #indent-width-label {
    cursor: pointer;
    margin-right: 3px;
}

#indent-type:hover, #indent-width-label:hover {
    text-decoration: underline;
}

#indent-width-input {
    font-size: 11px;
    font-weight: @font-weight-semibold;
    height: 13px;
    line-height: 1;
    vertical-align: middle;
    color: @tc-text;
    margin: 0;
    padding: 0 3px 2px;
    position: relative;
    left: 0;
    top: -1px;
    width: 6px;
    transition: 0.1s linear all;
}

#indent-width-input:focus {

}

#indent-width-input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

#editor-holder {
    position: relative;

    /* Placeholder shown when there is no editor open */
    #not-editor {
        height: 100%;
        .vbox;
        .box-pack(center);
        .box-align(center);
        background: @background-color-3 url('images/no_content_bg.svg') no-repeat center 45%;
    }

    /* Image Preview */
    #image-holder {
        overflow: hidden;
        position: absolute;
        top: 0px;
        right: 0px;
        bottom: 0px;
        left: 0px;
        text-align: center;
        display: none;
        #img-centering {
            display: inline-block;
            vertical-align: middle;
            margin-top: -50px; /* Offset as vertical align takes image metadata into account */
            max-width: 90%;
            max-height: 90%;
        }
        #img-data {
            font-weight: @font-weight-semibold;
        }
    }

    #image-holder:before {
        content: '';
        display: inline-block;
        height: 100%;
        margin-right: -0.25em; /* Adjusts for spacing */
        vertical-align: middle;
    }

    #img-preview {
        background: url(images/preview_bg.png);
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.36);
        max-height: 90%;
    }

    #img-header {
        display: inline-block;
        width: 100%;
        height: 38px;
        margin-bottom: 15px;
    }

    #img-data,
    #img-path {
        text-align: left;
        .user-select(text);
        white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
    }

    #img-data::selection,
    #img-path::selection {
        background: @selection-color-focused;
    }

    #img {
        position: relative;
    }

    .img-guide,
    #img-preview {
        cursor: none;
    }

    #img-scale {
        display: block;
        position: absolute;
        top: 5px;
        left: 5px;
        width: 40px;
        text-align: center;
        background-color: rgba(0, 0, 0, 0.8);
        color: #fff;
        border-radius: 3px;
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
    }

    #img-tip {
        display: block;
        position: absolute;
        text-align: left;
        white-space: nowrap;
        padding: 6px 9px;
        color: #fff;
        background-color: rgba(0, 0, 0, 0.8);
        font-size: 11px;
        font-family: SourceCodePro;
        line-height: 13px;
        border-radius: 3px;
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.24);
    }

    #x-value,
    #y-value {
        text-align: right;
    }

    .tip-container {
        border: 0;
    }

    #horiz-guide {
        background-image: url("images/horizontal-dash.svg");
        background-repeat: repeat-x;
        width: 8px;
        height: 1px;
    }

    #vert-guide {
        background-image: url("images/vertical-dash.svg");
        background-repeat: repeat-y;
        width: 1px;
        height: 8px;
    }

    #horiz-guide,
    #vert-guide {
        position: absolute;
        display: block;
    }
}

.vert-resizer {
    position: absolute;
    height: 6px;
    width: 100%;
    z-index: @z-index-brackets-panel-resizer;
    opacity: 0;
    cursor: row-resize;
}

.horz-resizer {
    position: absolute;
    height: 100%;
    width: 6px;
    z-index: @z-index-brackets-panel-resizer;
    opacity: 0;
    cursor: col-resize;
}

.bottom-panel {
    background-color: @tc-gray-panel;
    display: none;
    height: 200px;
    border-top-style: solid;
    border-width: 1px;
    border-color: @tc-gray-panel-border;

    .check-all {
        margin: 7px 15px 7px 7px;
    }

    .toolbar {
        background-color: @tc-gray-panel-top-bar;
        border-bottom: @tc-gray-panel-top-bar-shadow;
        height: auto;
        padding-top: (@base-padding / 2);
        padding-bottom: (@base-padding / 2);
        z-index: @z-index-brackets-results-panel;
        box-shadow: @tc-gray-panel-bevel, @tc-small-shadow-top;
        .title {
            color: @tc-text;
            font-size: @label-font-size;
            font-weight: @font-weight-semibold;
        }
        .close {
            position: absolute;
            right: 10px;

            // vertically centers close button
            top: 50%;
            margin-top: -10px;
        }
    }

    .table-container {
        height: 170px;
        overflow: auto;

        .highlight {
            background: @bc-white;
            border-radius: 2px;
        }

        tr.selected td {
            background-color: @tc-selected-row;
            color: @bc-black;
        }
    }
}

.bottom-panel-table {
    td {
        font-size: 12px;
        padding-left: 15px;
        padding-right: 0;
        vertical-align: baseline;
    }

    .file-section > td {
        padding-left: 5px;
    }

    .line-number {
        color: @tc-light-weight-quiet-text;
        font-family: SourceCodePro;
        font-size: 11px;
        padding: 4px 0 0 15px;
        text-align: right;
        white-space: nowrap;
        width: 5px;
    }

    .dialog-filename {
        font-size: 13px;
        font-weight: @font-weight-semibold;
    }

    .dialog-path {
        font-size: 11px;
        font-weight: normal;
    }

    .line-text {
        width: 100%;
    }
}

#update-notification {
    .sprite-icon(0, 0, 24px, 24px, "images/updateSprites.svg");
}

#toolbar-go-live {
    // background-position is 0 0 for 24x24 icons
    // Default icon is for the 'disconnected' state
    // The 'connecting failed' (.warning) state also maps here
    .sprite-icon(0, 0, 24px, 24px, "images/live_development_sprites.svg");
    // 'Connected' state
    &.success {
        .sprite-swap(0, 24px);
    }
    // 'Connection in progress' state
    &.info {
        .sprite-swap(0, 48px);
    }
    // 'Out-of-sync' state
    &.out-of-sync {
        .sprite-swap(0, 72px);
    }
    // 'sync-error'
    &.sync-error {
        .sprite-swap(0, 96px);
    }
}

#toolbar-extension-manager {
    .sprite-icon(0, 0, 24px, 24px, "images/topcoat-plugin-20.svg");
}

/* Project panel */

#working-set-header {
    height: 19px;
    padding: 10px 0 9px 12px;
    background: #3C3F41;
    color: @project-panel-text-2;
    text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.5);
    overflow: hidden;
}

#sidebar {
    position: relative;
    white-space: nowrap;
}

#sidebar-resizer {
    position: absolute;
    width: 6px;
    height: 100%;
    z-index: @z-index-brackets-sidebar-resizer;
    opacity: 0;
    cursor: col-resize;
}

#project-files-header {
    border-top: 1px solid #56595a;
    padding: 8px 0 9px 12px;
    font-size: 13px;
    color: @project-panel-text-2;
    overflow: hidden;
}

#open-files-container {
    .box-flex(0);
    background: #3C3F41;
    padding: 0px;
    max-height: 200px; // TODO (Issue #276): it would be nicer to have this be 50%, but that doesn't seem to work

    ul {
        list-style-type: none;
        margin: 0;
        padding-bottom: 23px;
    }

    li {
        position: relative; // so that children can be positioned absolute
        line-height: 18px;
        padding: 0 0 0 8px;
        min-height: 18px;
        vertical-align: baseline;

        &.selected a {
            color: @open-working-file-name-highlight;
        }

        &.selected .extension {
            color: @open-working-file-ext-highlight;
        }
    }

    a {
        color: #fff;

        font-size: 13px;
        text-decoration: none;

        display: block;
        height: 16px;
        line-height: 15px;
        margin-left: 18px;
        padding: 3px (@sidebar-triangle-size * 2) 3px 0;

        cursor: default;

        .directory {
            font-size: 11px;
        }
    }

    .extension, .directory {
        color: @project-panel-text-2;
    }
}

.sidebar-selection {
    background: url("images/active_back.png") no-repeat top right;
    height: 22px;
    position: absolute;
}

.sidebar-selection-triangle {
    background: url("images/active_back.png");
    width: 9px; /* quiet scrollbar width */
    height: 22px;
    position: fixed;

    z-index: @z-index-brackets-selection-triangle; /* scroller-shadow appears above this triangle */
}

.sidebar-selection-triangle.triangle-visible:before {
    content: "";

    border-top: @sidebar-triangle-size solid transparent;
    border-bottom: (@sidebar-triangle-size - 1) solid transparent;
    border-left: @sidebar-triangle-size solid #2D2E30;

    display: block;
    position: absolute;
    top: -1px;
    right: -9px;
    width: 0;
    height: 0;

    .scale-x(0.8, right, top);
}

//Initially start with the open files hidden, they will get show as files are added
#open-files-container {
    display:none;
}

#project-files-container {
    .box-flex(1);

    .jstree-brackets li > a {
        padding-right: (@sidebar-triangle-size * 2);
    }

    ul {
        padding-left: 8px;
    }

    > ul {
        padding-bottom: 24px;
    }
}

.scroller-shadow {
    background-size: 100%;
    background-repeat: no-repeat;
    height: 5px;
    position: fixed;
    z-index: @z-index-brackets-scroller-shadow;

    &.top {
        #gradient > .vertical(rgba(0,0,0,0.1), rgba(0,0,0,0));
        background-position: 0 -5px;
        background-color: transparent; /* override background-color: @endColor from #gradient.vertical */
    }

    &.bottom {
        #gradient > .vertical(rgba(0,0,0,0), rgba(0,0,0,0.1));
        background-position: 0 5px;
        background-color: transparent; /* override background-color: @endColor from #gradient.vertical */
    }
}

@jstree-sprite-size: 18px;  // this is hardcoded in jsTree's JS code

/** Classes for icons from jsTreeSprites.svg
*/
.jstree-sprite {
    background-image: url("images/jsTreeSprites.svg");
    background-repeat: no-repeat;
    background-color: transparent;
    vertical-align: middle;
    width: @jstree-sprite-size;
    height: @jstree-sprite-size;
}

/** Overriding jsTreeTheme.less
*/
.jstree-brackets .jstree-no-dots .jstree-open > ins {
    background-position: 7px -8px;
    -webkit-transform: translateZ(0) rotate(90deg);
    -webkit-filter: drop-shadow(1px 0 1px rgba(0, 0, 0, 0.36));
}

.jstree-brackets .jstree-no-dots .jstree-closed > ins {
    background-position: 7px -8px;
    -webkit-transform: translateZ(0); /* Need this to make sure that the svg isn't blurry on retina. */
    -webkit-filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.36));
}

/** Classes for icons from bracketSprites.png
*/
.bracket-sprite {
    background-image: url("images/close_btn.svg");
    background-repeat: no-repeat;
    background-color: transparent;
    vertical-align: middle;
    width: 15px;
    height: 16px;
}

.file-status-icon {
    margin: 2px 0 0 8px;
    .bracket-sprite;
    display: inline-block;
    position: absolute;
    left: 0px;
    top: 1px;

    &.dirty {
        background-position: -30px 1px;
    }

    &.can-close {
        background-position: 0 0;
    }

    &.can-close:hover {
        background-position: -15px 0;
    }

    &.can-close:active {
        background-position: -15px 0;
        opacity: @tc-icon-down;
    }
}

/* Styles for inline editors */

.inline-text-editor {
    line-height: 0px;
}

.inline-widget {
    position: relative;
    overflow: hidden;

    background-color: @tc-lighter-gray;
    min-width: 250px;
    cursor: default;

    &.animating {
        // Make the animation use the GPU--especially important for retina.
        -webkit-transform: translateZ(0);
        transform: translateZ(0);

        transition: height 250ms cubic-bezier(0, 1.02, 0.6, 1);
    }

    .CodeMirror {
        /* remove CodeMirror default height: 300px */
        height: auto;
    }

    .inline-editor-header {
        display: inline-block;
        padding: 10px 10px 0px 40px;

        .filename {
            vertical-align: middle;
            font-family: @sansFontFamily;
            font-size: 13px;
            color: @bc-black;

            // Filename header is clickable (it's an <a> tag, so we get underscore on hover by
            // default; but the hand cursor is shut off by Bootstrap's reset stylesheet)
            cursor: pointer;

            .dirty-indicator {
                .bracket-sprite;
                display: inline-block;
                background-position: -32px 2px;
                padding-top: 5px;
            }

            .line-number {
                color: @inline-color-2;
            }
        }
    }

    .shadow {
        display: block;
        height: 4px;
        width: 100%;
        position: absolute;
        content: " ";
        left: 0;
        z-index: @z-index-brackets-inline-editor-shadow;
    }

    .shadow.top {
        top: 0px;
        background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0));
    }

    .shadow.bottom {
        bottom: 0px;
        background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.1));
    }

    .CodeMirror-scroll {
        background-color: transparent;

        .CodeMirror-linenumbers {
            background-color: @tc-lighter-gray;
        }
    }

    .close {
        position: absolute;
        left: 15px;
        top: 10px;
        margin-right: 30px;
    }

}

/* CSSInlineEditor rule list */
.related-container {
    @top-margin: 12px;

    float: right;
    position: relative;
    min-height: 100%;
    font-family: @sansFontFamily;
    width: 250px;
    max-width: 50%;
    overflow: hidden;
    background: @inline-background-color-2;

    .selection {
        width: 100%;
        background: #d0d5d5;
        position: absolute;
        border-top: 1px solid darken(@inline-background-color-3, @bc-color-step-size);
        border-bottom: 1px solid lighten(@inline-background-color-3, @bc-color-step-size);
        top: @top-margin;

        &.animate {
            transition: top 0.1s ease-out;
        }
    }

    /*
     * CSS triangle hack with anti-alias workarounds:
     * (a) Use selection-background-color instead of transparent.
     * (b) Use transform scaleX and origin to adjust width.
     */
    .selection:before {
        content: " ";
        position: absolute;
        width: 0;
        height: 0;
        border-top: @inline-triangle-size solid @inline-background-color-3;
        border-bottom: @inline-triangle-size solid @inline-background-color-3;
        border-left: @inline-triangle-size solid @inline-background-color-1;
        margin-top: -@inline-triangle-size;
        top: 50%;
        .scale-x(0.9, left, top);
    }

    .related {
        font-size: 12px;
        position: absolute;
        top: 0;
        left: 1px;
        width: 100%;

        ul {
            margin: 0;
            padding: @top-margin 0px;
            list-style: none;
        }

        li {
            color: @tc-emphasized-text;
            margin: 0;
            overflow: hidden;
            padding: 2px 0px 2px 15px;
            text-overflow: ellipsis;
            white-space: nowrap;

            .related-file {
                color: @tc-input-placeholder-text;
            }
        }

        .selected {
            color: @tc-light-weight-text;
            transition: color 0.1s ease-out .15s;
        }
    }
}

.inline-editor-message {
    color: @tc-input-placeholder-text;
    font-family: @sansFontFamily;
    font-size: 12px;
    line-height: 17px;
    height: 20px;
    padding: 10px 0 40px 50px;
}

/* This text is used to force the code editor's font to be loaded early on if it's a
   web font. This is necessary in order for the editor's horizontal measurement of text
   to work properly.

   In the future, when we allow the user to switch fonts, we'll need to make sure to
   update the font for this text item whenever the user switches. We'll also need to
   wait to initiate a re-measure in CodeMirror until the new font is loaded (if they
   choose a web font). This library allows for checking if a web font is loaded:

     http://code.google.com/apis/webfonts/docs/webfont_loader.html
*/
.dummy-text {
    position: fixed;
    top: -10000px;
    .code-font();
}

.platform-mac .dummy-text {
    .code-font-mac();
}

/* Find in Files results panel - temporary UI, to be replaced with a richer search feature later */

#search-results .title, #replace-all-results .title {
    .sane-box-model;
    padding-right: 20px;
    width: 100%;
    line-height: 25px;

    .flex-box;
    .contracting-col {
        .flex-item(0);
        min-width: 1px;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .fixed-col {
        .flex-item(0, 0);
    }
    .pagination-col {
        .flex-item(1, 0);
        min-width: 100px;
    }
    .replace-col {
        .flex-item(1, 0);
        min-width: 120px;
        padding: 0 15px;
    }
    .first-page,
    .prev-page,
    .next-page,
    .last-page {
        .jstree-sprite;
        width: 6px;
        display: inline-block;
        margin: 0 2px;
        background-position: 0px 4px;
    }
    .first-page {
        background-position: 0px -80px;
        margin-left: 10px;
    }
    .prev-page {
        background-position: 0px -24px;
    }
    .last-page {
        background-position: 0px -52px;
    }
    .disabled {
        opacity: 0.3;
    }
}

#search-results .disclosure-triangle {
    .jstree-sprite;
    display: inline-block;
    &.expanded {
        // Unfortunately, the way jsTree sprites are aligned within their 18px boxes doesn't look good in
        // other contexts, so we need some tweaks here instead of straight multiples of @jstree-sprite-size
        background-position: 7px 5px;
        -webkit-transform: translateZ(0) rotate(90deg);
    }
    &.collapsed {
        background-position: 7px 5px;
    }
}

/* Modal bar for Find/Quick Open */

.modal-bar {
    display: block;
    text-align: left;

    font-family: @sansFontFamily;
    font-size: 14px;
    color: @tc-text;
    background: @tc-gray-panel;
    overflow: hidden;
    padding: 5px 4px 4px 14px;

    -webkit-transform: translate(0, 0); // Prefix still required.
    transition: -webkit-transform 66ms cubic-bezier(0, 0.62, 0.04, 0.99);
    z-index: @z-index-brackets-modalbar;

    body.in-browser &,
    body:not(.has-appshell-menus) & {
        // Separator line between us and the HTML menu/titlebar above
        border-top: 1px solid darken(@background-color-3, @bc-color-step-size);
    }

    &.popout {
        position: absolute;
        left: 0;
        right: 0;
        top: 0;
    }

    &.offscreen {
        -webkit-transform: translate(0, -44px);
        transform: translate(0, -44px);
        transition: -webkit-transform 266ms cubic-bezier(0, 0.56, 0, 1);
        transition: transform 266ms cubic-bezier(0, 0.56, 0, 1);

        body:not(.has-appshell-menus) & {
            top: 37px;
        }
    }

    input {
        font-family: @sansFontFamily;
        outline: none;
        width: 20em;
        margin: 5px 5px 0;
        position: relative;
        top: -3px;
        &.no-results {
            border: 1px solid #bc0023;
            box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.12), 0 0 0 2px rgba(255, 0, 120, 0.5);
        }
    }

    .message {
        display: inline-block;
    }

    .error {
        display: none;

        .alert {
            padding-top: 4px;
            padding-bottom: 4px;
        }
    }

    .navigator {
        display: none;
        button {
            margin: 2px 1px 3px;
        }
    }
}

// Search result highlighting - CodeMirror highlighting is pretty constrained. Highlights are
// blended on TOP of the selection color. The "current" search result is indicated by selection,
// so we want the selection visible underneath the highlight. To do this, the highlight must be
// transparent; it has to look good atop both the selection color AND the regular text bg color.
.CodeMirror-searching {
    // Highlight color, overlaid on top of the .find-highlighting color
    background-color: @cm-match-highlight;
    border-radius: @tc-inline-border-radius;
    box-shadow: @tc-small-shadow-bottom;
    color: @match-text !important;
}
.CodeMirror.find-highlighting div.CodeMirror-selected,
.CodeMirror .CodeMirror.find-highlighting div.CodeMirror-selected {
    // Selection color while highlighting shown - ALWAYS has the .CodeMirror-searching color
    // blended atop it.
    // Note: the 2nd selector reflecting CM nesting is needed to override the similar rules in
    // brackets_codemirror_override.less (see the note about #324).
    background: @cm-current-match-highlight;
    border-radius: @tc-inline-border-radius;
}
#find-counter {
    font-weight: @font-weight-semibold;
    padding: 0 5px;
}

.tickmark-track {
    position: absolute;
    bottom: 0;
    top: 0;
    right: 0;
    width: 16px;
    z-index: @z-index-cm-max;
    pointer-events: none;

    .tickmark {
        position: absolute;
        width: 16px;
        body.platform-mac & { width: 15px; }

        height: 1px;
        background-color: #eddd23;
        border-top: 1px solid #e0d123;
        border-bottom: 1px solid #d4c620;
        opacity: 0.85;  // allow thumb to show through
    }
}

/* Quick Open search bar & dropdown */

.smart_autocomplete_container {

    // the borders show up even if the container is empty, must set height to zero using JS.
    border: 1px solid @tc-gray-panel-border;

    background-color: @tc-gray-panel;
    border-radius: 0 0 4px 4px;
    box-shadow: @tc-normal-shadow-bottom;

    // so that border won't show when height is 0.
    box-sizing: border-box;

    // using this to fix the spacing that breaks item seperators and had to use !important to override inline css
    width: 434px !important;

    /* smart auto complete doesn't correctly position the container
     * so these specific padding and margin values are necessary*/
    padding: 0px;
    margin: 9px 0 0;

    .quick-open-path {
        color: #666;
        font-size: 11px;
        letter-spacing: 0.04em;
        line-height: 11px;
    }

    li {
        color: #222;
        line-height: 15px;
        list-style: none;
        cursor: default;
        padding: 6px 10px;

        &:nth-child(odd) {
            background-color: @tc-lighter-gray;
        }

        &:hover {
            background-color: @tc-hover-highlight;
        }

        &.smart_autocomplete_highlight {
            background-color: @tc-highlight;
        }
    }
}

.quicksearch-pathmatch,
.quicksearch-namematch {
    font-weight: @font-weight-semibold;
}

.quicksearch-pathmatch {
    color: #555;
}

/* Spinner */

.spinner {
    display: inline-block;
    vertical-align: middle;
    margin-top: -2px;
    width: 12px;
    height: 12px;
    background: url("images/spinner_small_sprites12.png") no-repeat;
    visibility: hidden;

    &.spin {
        -webkit-animation: spinner-sprites-12 1.2s steps(10) infinite;
        visibility: visible;
    }

    &.large {
        width: 36px;
        height: 36px;
        margin-top: 0;
        background: url("images/spinner_large_sprites36.png") no-repeat;

        &.spin {
            -webkit-animation: spinner-sprites-36 1.2s steps(10) infinite;
        }
    }
}
// Retina versions
@media only screen and (-webkit-min-device-pixel-ratio: 2),
       only screen and (min-device-pixel-ratio: 2) {
    .spinner {
        background-image: url("images/spinner_small_sprites12@2x.png");
        background-size: 120px 12px;

        &.large {
            background: url("images/spinner_large_sprites36@2x.png") no-repeat;
            background-size: 360px 36px;
        }
    }
}

/* Problems panel & CodeInspection status bar indicator */

#status-indicators #status-inspection {
    border: none;
    cursor: default;
    width: 13px;
}

.inspection-disabled {
    background: url(images/topcoat-inactive-15.svg) 9px 5px no-repeat;
}

.inspection-errors {
    background: url(images/topcoat-warning-15.svg) 9px 5px no-repeat;
}

.inspection-errors:hover {
    background-color: rgba(0, 0, 0, 0.03);
}

.inspection-errors:active {
    background-color: rgba(0, 0, 0, 0.05);
}

.inspection-valid {
    background: url(images/topcoat-okay-15.svg) 9px 5px no-repeat;
}

#problems-panel {
    .user-select(text);  // allow selecting error messages for easy web searching
    .line {
        text-align: right;  // make line number line up with editor line numbers
    }
}

/* Line up label text and input text */
label input {
    position: relative;
    top: -2px;
}

/* Live Preview */
.live-preview-sync-error .CodeMirror-linenumber {
    background-color: @live-preview-sync-error-background;
    color: @live-preview-sync-error-color;
}


// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

// NOTE: These type checking functions intentionally don't use `instanceof`
// because it is fragile and can be easily faked with `Object.create()`.
function isArray(ar) {
  return Array.isArray(ar);
}
exports.isArray = isArray;

function isBoolean(arg) {
  return typeof arg === 'boolean';
}
exports.isBoolean = isBoolean;

function isNull(arg) {
  return arg === null;
}
exports.isNull = isNull;

function isNullOrUndefined(arg) {
  return arg == null;
}
exports.isNullOrUndefined = isNullOrUndefined;

function isNumber(arg) {
  return typeof arg === 'number';
}
exports.isNumber = isNumber;

function isString(arg) {
  return typeof arg === 'string';
}
exports.isString = isString;

function isSymbol(arg) {
  return typeof arg === 'symbol';
}
exports.isSymbol = isSymbol;

function isUndefined(arg) {
  return arg === void 0;
}
exports.isUndefined = isUndefined;

function isRegExp(re) {
  return isObject(re) && objectToString(re) === '[object RegExp]';
}
exports.isRegExp = isRegExp;

function isObject(arg) {
  return typeof arg === 'object' && arg !== null;
}
exports.isObject = isObject;

function isDate(d) {
  return isObject(d) && objectToString(d) === '[object Date]';
}
exports.isDate = isDate;

function isError(e) {
  return isObject(e) && objectToString(e) === '[object Error]';
}
exports.isError = isError;

function isFunction(arg) {
  return typeof arg === 'function';
}
exports.isFunction = isFunction;

function isPrimitive(arg) {
  return arg === null ||
         typeof arg === 'boolean' ||
         typeof arg === 'number' ||
         typeof arg === 'string' ||
         typeof arg === 'symbol' ||  // ES6 symbol
         typeof arg === 'undefined';
}
exports.isPrimitive = isPrimitive;

function isBuffer(arg) {
  return arg instanceof Buffer;
}
exports.isBuffer = isBuffer;

function objectToString(o) {
  return Object.prototype.toString.call(o);
}


<!DOCTYPE html>

	<meta charset="utf-8">
	<title>jQuery UI Sortable - Display as grid</title>
	<link rel="stylesheet" href="../../themes/base/jquery.ui.all.css">

	<link rel="stylesheet" href="../demos.css">

1

2

3

4

5

6

7

8

9

10

11

12

	To arrange sortable items as a grid, give them identical dimensions and
	float them using CSS.


test:
	@./node_modules/.bin/mocha \
		--reporter spec \
		--require should

.PHONY: test


(offsetY >= scaleDivTop && offsetY <= scaleDivBottom)) {

// But hide it only if the pixel under mouse is also in the image.

if (offsetX < (imagePos.left + imgWidth) &&

// See whether the cursor is no longer inside the hidden scale div.

if ((offsetX < scaleDivLeft || offsetX > scaleDivRight) ||

(offsetY < scaleDivTop || offsetY > scaleDivBottom)) {

} else if ((offsetX >= scaleDivLeft && offsetX <= scaleDivRight) &&