lclass("TemplateBrowser", [LEventHandling], {
	cons: function(templateIds, imageUrlBase, inputId, catInputId, imageWidth, imageSpacing) {
        this.imageUrlBase = imageUrlBase;
        this.templates = [];
        this.categories = {0: ""};
        this.imageWidth = imageWidth || TemplateBrowser.IMAGE_WIDTH;
        this.imageSpacing = imageSpacing || TemplateBrowser.IMAGE_SPACING;

		var i, id, p, catId = 0, catName;

        for (i = 0; i < templateIds.length; i++) {
            id = templateIds[i];
            if (typeof id == "number") {
                this.templates.push([catId, id, ""]); // deprecated
            } else if (typeof id == "string") {
                p = id.indexOf("|");
                if (p == -1) {
                    p = id.indexOf(":")
                    if (p != -1) {
                        catId = parseInt(id.substring(0, p));
                        this.categories[catId] = id.substring(p + 1);
                    }
                } else {
                    this.templates.push([catId, parseInt(id.substring(0, p)), id.substring(p + 1)]);
                }
            }
        }
        
        var ids = ["TemplateBrowserLeft", "TemplateBrowserRight", "TemplateBrowserLoading"];
		
		this.els = {};
		for (i in ids) {
			this.els[ids[i]] = $(ids[i]);
		}
		
		this.els.input = $(inputId);
		this.els.catInput = $(catInputId);

		this.els.TemplateBrowserLeft.attachEvent("click", this, this.scrollLeft);
		this.els.TemplateBrowserRight.attachEvent("click", this, this.scrollRight);

		this.el = $("TemplateBrowserCards");

		this.el.append((this.primaryRow = new ImageRow(this.imageWidth, this.imageSpacing)).el);
		this.el.append((this.secondaryRow = new ImageRow(this.imageWidth, this.imageSpacing)).el);
		
		this.primaryRow.attachEvent("load", this, this.imagesLoaded);
		this.secondaryRow.attachEvent("load", this, this.imagesLoaded);
        this.primaryRow.attachEvent("imageclick", this, this.imageClicked);
        this.secondaryRow.attachEvent("imageclick", this, this.imageClicked);

		this.anim = {};
		this.anim.scroll = [];

		this.x = 0;
		
		this.continueScroll = -1;
		this.updateAfterLoad = false;

		this.updateWidth();
		
		this.widthTimer = new LTimer(500, this, this.widthTimerTick);
		lwindow.attachEvent("resize", this, this.windowResized);
	},

	windowResized: function() {
		if (this.loadInProgress) {
			this.updateAfterLoad = true;
		} else {
			this.widthTimer.reset();
		}
	},

	widthTimerTick: function() {
		this.updateWidth();
	},
	
	updateWidth: function() {
		this.setLoading(true);
		this.loadInProgress = true;
		this.initialLoad = true;

		var width = this.el.offsetWidth();
		var space = (width - this.imageSpacing) / (this.imageWidth + this.imageSpacing)
		this.numImages = Math.ceil(space);
		this.scrollAmount = Math.floor(space);
		if (this.numImages < 2) {
			this.numImages = 2;
		}
//		var rowWidth = this.numImages * TemplateBrowser.IMAGE_WIDTH + (this.numImages - 1) * TemplateBrowser.IMAGE_SPACING;
//		var animWidth = rowWidth + TemplateBrowser.IMAGE_SPACING;
//		var primaryX = Math.floor((width - rowWidth) / 2) + "px";
		var scrollX = this.scrollAmount * this.imageWidth + (this.scrollAmount + 1) * this.imageSpacing;
		var primaryX = this.imageSpacing;

		this.primaryRow.setNumImages(this.numImages);
		this.secondaryRow.setNumImages(this.numImages);

		if (this.anim.scroll[0]) {
			delete this.anim.scroll[0];
			delete this.anim.scroll[1];
		}

		this.anim.scroll[0] = new LAnimation([
			[this.primaryRow.el,
				[0, "left: " + primaryX + "px"],
				[1000, "left> -" + (scrollX - this.imageSpacing * 2) + "px"]
			],
			[this.secondaryRow.el,
				[0, "left: " + scrollX + "px"],
				[1000, "left> " + primaryX + "px"]
			]
		]);
		this.anim.scroll[0].setFps(30);
		this.anim.scroll[0].setTween(LAnimation.smoothEnd);
		this.anim.scroll[0].attachEvent("finish", this, this.animationFinished);
		this.anim.scroll[1] = new LAnimation([
			[this.primaryRow.el, 
				[0, "left: " + primaryX + "px"],
				[1000, "left> " + scrollX + "px"]
			],
			[this.secondaryRow.el,
				[0, "left: -" + (scrollX - this.imageSpacing * 2) + "px"],
				[1000, "left> " + primaryX + "px"]
			]
		]);
		this.anim.scroll[1].setFps(30);
		this.anim.scroll[1].setTween(LAnimation.smoothEnd);
		this.anim.scroll[1].attachEvent("finish", this, this.animationFinished);

		this.primaryRow.el.style().left = primaryX + "px";
		this.secondaryRow.el.style().left = "10000px";
		//this.secondaryRow.el.style().display = "none";

		this.primaryRow.reset();

        this.setImages(this.primaryRow);
	},

	setLoading: function(b) {
		this.els.TemplateBrowserLoading.style().display = b ? "block" : "none";
	},

	setImages: function(row) {
		var i, idx, tpl;
        var catId = -1;
        var catText = "";

		row.reset();

		for (i = 0; i < this.numImages; i++) {
            idx = (this.x + i) % this.templates.length;
            while (idx < 0) {
                idx += this.templates.length; 
            }

            catText = "";

            tpl = this.templates[idx];
            if (catId != tpl[0]) {
                catId = tpl[0];
                catText = this.categories[catId];
                if (i > 0) {
                    row.setLastInCategory(i - 1);  
                }
            }
			row.setImage(i, this.imageUrlBase.format(catId, tpl[1]), catId, catText, tpl[1], tpl[2]);
		}
	},

	scrollLeft: function() {
		return this.scroll(1);
	},

	scrollRight: function() {
		return this.scroll(0);
	},

	scroll: function(dir) {
		if (this.loadInProgress) {
			this.continueScroll = dir;
			return false;
		}
		this.scrolldir = dir;
		this.loadInProgress = true;
		if (dir == 0) {
			this.x += this.scrollAmount;
		} else {
			this.x -= this.scrollAmount;
		}
		this.setLoading(true);
		this.secondaryRow.el.style().display = "block";
		this.setImages(this.secondaryRow);
		return false;
	},

	imagesLoaded: function() {
		if (this.initialLoad) {
			this.initialLoad = false;
			this.loadInProgress = false;
		} else {
			this.anim.scroll[this.scrolldir].timelines[0][0] = this.primaryRow.el;
			this.anim.scroll[this.scrolldir].timelines[1][0] = this.secondaryRow.el;
			this.anim.scroll[this.scrolldir].start();
		}
		this.setLoading(false);
	},

	animationFinished: function() {
		var temp;

		temp = this.primaryRow;
		this.primaryRow = this.secondaryRow;
		this.secondaryRow = temp;
		this.secondaryRow.el.style().display = "none";

		this.loadInProgress = false;
		
		if (this.updateAfterLoad) {
			this.updateWidth();
			this.updateAfterLoad = false;
		} else if (this.continueScroll > -1) {
			if (this.continueScroll == 1) {
				this.scrollLeft();
			} else {
				this.scrollRight();
			}

			this.continueScroll = -1;
		}
	},

    imageClicked: function(e) {
        this.els.input.setValue(e.getAttribute("id"));
        this.els.catInput.setValue(e.getAttribute("catId"));
        if (typeof __doPostBack != "undefined") {
            __doPostBack();
        }
    }
}, {
	IMAGE_WIDTH: 158,
	IMAGE_SPACING: 11 
});

lclass("ImageRow", [LEventHandling], {
	cons: function(imageWidth, imageSpacing) {
		this.el = new LElementNode("ul");
		
        this.imageWidth = imageWidth;
        this.imageSpacing = imageSpacing;
		this.items = [];

		this.numImages = 0;
	},
	
	setNumImages: function(numImages) {
		if (numImages > this.numImages) {
			var i, li, img, item, elCat;

			for (i = this.numImages; i < numImages; i++) {
				this.el.append(item = this.items[i] = new LElementNode("li",
                    elCat = new LElementNode("div"),
					img = new LElementNode("img"),
                    elText = new LElementNode("span", " ")
				));
                item.apply({
                    width: this.imageWidth + "px",
                    marginRight: this.imageSpacing + "px"
                });
                item.elCat = elCat;
                item.elText = elText;
				img.attachEvent("load", this, this.imageLoaded);
                item.attachEvent("click", this, this.imageClicked);
                //elText.attachEvent("click", this, this.imageClicked);
			}

			this.numImages = numImages;
			return true;
		} else if (numImages < this.numImages) {
			var i;
			for (i = this.numImages - 1; i >= numImages; i--) {
				this.items[i].removeSelf();
				delete this.items[i];
			}

			this.numImages = numImages;
			return false;
		}
	},

	reset: function() {
		this.toLoad = this.numImages;
        for (i = 0; i < this.numImages; i++) {
            this.items[i].removeClass("LastInCategory");  
        }
	},

	setImage: function(i, src, catId, catText, id, imgText) {
        var elCat = this.items[i].firstChild();
        var elImg = elCat.nextSibling();
        var elText = elImg.nextSibling();
		elImg.setAttribute("src", src);
        this.items[i].__catId = catId;
        this.items[i].__id = id;
        elCat.setText(catText);
        elText.setText(imgText);
	},

    setLastInCategory: function(i) {
        this.items[i].addClass("LastInCategory");  
    },

	imageLoaded: function() {
		if (--this.toLoad == 0) {
			this.fireEvent("load");
		}
	},

    imageClicked: function(e) {
        this.fireEvent("imageclick", {id: e.thisElement().__id, catId: e.thisElement().__catId});
    }
});

lclass("SPDrawArea", {
	cons: function(params) {
		$PM(this, params, {
			element: "",
			w: 0, h: 0
		});
		this.el = $(this.element);
		if (this.w > 0 && this.h > 0) {
			this.el.apply({width: this.w + "px", height: this.h + "px"});
		} else {
			this.w = this.el.offsetWidth;
			this.h = this.el.offsetHeight;
		}
		this.selectedImage = null;

		lwindow.attachEvent("resize", this, this.windowResized);

		this.windowResized();
	},

	add: function(item) {
		item.area = this;
		item.init();

		if (item._instanceOf(SPDrawAreaImageItem)) {
			this.selectedImage = item;
		}
	},

	zoomIn: function() {
		if (this.selectedImage) {
			this.selectedImage.zoomBy(1.05);
		}
		return false;
	},

	zoomOut: function() {
		if (this.selectedImage) {
			this.selectedImage.zoomBy(1.0 / 1.05);
		}
		return false;
	},

	windowResized: function() {
		this.x = this.el.offsetLeft();
		this.y = this.el.offsetTop();
	},

	relativeMousePosition: function(e) {
		var mpos = e.mousePosition();
		return {x: mpos.x - this.x, y: mpos.y - this.y};
	}
});

lclass("SPDrawAreaItem", {});

lclass("SPDrawAreaTextItem", [SPDrawAreaItem], {
	cons: function(params) {
		$PM(this, params, {
			inputId: "",
			x: 0, y: 0, w: 0, h: 0,
			text: ""
		});
	},

	init: function() {
		var styles = {
			top: this.y + "px",
			left: this.x + "px",
			width: this.w + "px",
			height: this.h + "px"
		};
		this.el = {};
		this.el.div = new LElementNode("div");
		this.el.div.setClass("DrawAreaText");
		this.el.div.setHTML(this.text.replace(/\n/g, "<br />").replace(/\r/g, ""));
		this.el.div.apply(styles);
		this.el.div.attachEvent("click", this, this.startEditing);

		this.el.textarea = new LElementNode("textarea");
		this.el.textarea.apply(styles);
		this.el.textarea.style().display = "none";
		this.el.textarea.attachEvent("click", function(e) { e.stop(); });
		this.area.el.append(this.el.div, this.el.textarea);

		this.el.input = $(this.inputId);
		this.el.input.setValue(this.text);
	},

	startEditing: function(e) {
		this.el.textarea.setValue(this.text);

		this.el.div.style().display = "none";
		this.el.textarea.style().display = "block";

		ldocument.attachEvent("click", this, this.finishEditing);

		e.stop();
	},

	finishEditing: function() {
		ldocument.detachEvent("click", this, this.finishEditing);
		this.text = this.el.textarea.value();
		this.el.div.setHTML(this.text.replace(/\n/g, "<br />").replace(/\r/g, ""));
		this.el.input.setValue(this.text);

		this.el.textarea.style().display = "none";
		this.el.div.style().display = "block";
	}
});

lclass("SPDrawAreaImageItem", [SPDrawAreaItem], {
	cons: function(params) {
		$PM(this, params, {
			inputId: "",
			x: 0, y: 0, w: 128, h: 128,
			imageUrl: "", originalW: 256, originalH: 256,
			cropX: false, cropY: false, cropW: false, cropH: false,
			shaderTop: 0, shaderRight: 0, shaderBottom: 0, shaderLeft: 0,
			shaderAll: false,
			borderStyle: {display: "none"}
		});

		if (this.shaderAll !== false) {
			this.shaderTop = this.shaderRight = this.shaderBottom = this.shaderLeft = this.shaderAll;
		}

		this.imageRatio = this.originalW / this.originalH;
		this.areaRatio = this.w / this.h;
		
		if (this.cropX === false) {
			this.autoCrop();
		}

		var zoomFactor = this.w / this.cropW;

		this.imageX = this.x - this.cropX * zoomFactor;
		this.imageY = this.y - this.cropY * zoomFactor;
		this.imageW = this.originalW * zoomFactor;
		this.imageH = this.originalH * zoomFactor;
	},

	autoCrop: function() {
		if (this.imageRatio > this.areaRatio) {
			// Clamp height
			this.cropH = this.originalH;
			this.cropY = 0;
			this.cropW = this.cropH * this.areaRatio;
			this.cropX = (this.originalW - this.cropW) / 2;
		} else {
			// Clamp width
			this.cropW = this.originalW;
			this.cropX = 0;
			this.cropH = this.cropW / this.areaRatio;
			this.cropY = (this.originalH - this.cropH) / 2;
		}
		//alert(this.cropW + " " + this.cropX + " " + this.cropY + " " + this.cropH);
	},

	init: function() {
		this.el = {};
		
		this.el.root = new LElementNode("div");
		this.el.root.setClass("DrawAreaImage");
		this.el.root.apply({
			top: this.y + "px",
			left: this.x + "px",
			width: this.w + "px",
			height: this.h + "px"
		});

		this.el.img = new LElementNode("img", {src: this.imageUrl});
		this.el.root.append(this.el.img);

		this.el.handles = new LElementNode("div");
		this.el.handles.setClass("DrawAreaImageHandles");
		this.el.handles.attachEvent("mousedown", this, this.beginDrag);

		this._makeHandle("NE");
		this._makeHandle("SE");
		this._makeHandle("SW");
		this._makeHandle("NW");

		this.area.el.append(this.el.handles);

		this.el.shaders = new LElementNode("div");
		this.el.shaders.setClass("DrawAreaImageShaders");

		this._makeShader("Top", this.w - this.shaderLeft, this.shaderTop);
		this._makeShader("Right", this.shaderRight, this.h - this.shaderTop);
		this._makeShader("Bottom", this.w - this.shaderRight, this.shaderBottom);
		this._makeShader("Left", this.shaderLeft, this.h - this.shaderBottom);

		this.el.root.append(this.el.shaders);

		this.el.shaderBorder = new LElementNode("div");
		this.el.shaderBorder.setClass("DrawAreaImageShaderBorder");
		this.el.shaderBorder.apply(this.borderStyle);
		this.el.shaderBorder.apply({
			top: this.shaderTop + "px",
			left: this.shaderLeft + "px",
			width: (this.w - this.shaderLeft - this.shaderRight - 2) + "px",
			height: (this.h - this.shaderTop - this.shaderBottom - 2) + "px"
		});

		this.el.root.append(this.el.shaderBorder);

		this.area.el.append(this.el.root);

		this.el.input = $(this.inputId);

		if ($("DrawAreaDebugRect")) {
			this.debugMode = true;
		}

		this.updatePosition();

		this.mode = SPDrawAreaImageItem.MODE_NONE;
	},

	_makeHandle: function(direction) {
		var el = new LElementNode("div");
		el.setClass("Handle" + direction);
		var dir = SPDrawAreaImageItem["HANDLE_" + direction];
		el.attachEvent("mousedown", this, function(e) { return this.beginResize(e, dir); })
		this.el.handles.append(el);
	},

	_makeShader: function(edge, w, h) {
		if (w > 0 && h > 0) {
			var el = new LElementNode("div");
			el.setClass("Shader" + edge);
			el.apply({width: w + "px", height: h + "px"});
			this.el.shaders.append(el);
		}
	},

	updatePosition: function() {
		this.el.img.apply({
			top: Math.floor(this.imageY - this.y) + "px",
			left: Math.floor(this.imageX - this.x) + "px",
			width: Math.floor(this.imageW) + "px",
			height: Math.floor(this.imageH) + "px"
		});
		this.el.handles.apply({
			top: Math.floor(this.imageY) + "px",
			left: Math.floor(this.imageX) + "px",
			width: Math.floor(this.imageW - 2) + "px",
			height: Math.floor(this.imageH - 2) + "px"
		});

		/*var zoomFactor = this.w / this.cropW;

		this.imageX = this.x - this.cropX * zoomFactor;
		this.imageY = this.y - this.cropY * zoomFactor;
		this.imageW = this.originalW * zoomFactor;
		this.imageH = this.originalH * zoomFactor;*/

		var factor = this.originalW / this.imageW;

		this.cropW = Math.floor(this.originalW * this.w / this.imageW);
		this.cropH = Math.floor(this.originalH * this.h / this.imageH);
		this.cropX = Math.floor((this.x - this.imageX) * factor);
		this.cropY = Math.floor((this.y - this.imageY) * factor);

		this.el.input.setValue(this.cropX + ";" + this.cropY + ";" + this.cropW + ";" + this.cropH);

		if (this.debugMode) {
			var d = $("DrawAreaDebugRect");
			d.apply({
				top: this.cropY + "px",
				left: this.cropX + "px",
				width: (this.cropW - 2) + "px",
				height: (this.cropH - 2) + "px"
			});
		}

		//window.status = "Original: " + this.imageRatio + "Now: " + (this.imageW / this.imageH);
	},

	beginResize: function(e, dir) {
		if (this.mode != SPDrawAreaImageItem.MODE_NONE) {
			return false;
		}

		ldocument.attachEvent("mousemove", this, this.updateResize);
		ldocument.attachEvent("mouseup", this, this.endResize);

		this.mode = SPDrawAreaImageItem.MODE_RESIZE;

		var cx, cy;

		this.resizeDir = dir;

		switch (this.resizeDir) {
			case SPDrawAreaImageItem.HANDLE_SE:
				cx = this.imageX + this.imageW;
				cy = this.imageY + this.imageH;
				break;
			case SPDrawAreaImageItem.HANDLE_NW:
				cx = this.imageX;
				cy = this.imageY;
				this.initocx = this.imageX + this.imageW;
				this.initocy = this.imageY + this.imageH;
				break;
			case SPDrawAreaImageItem.HANDLE_NE:
				cx = this.imageX + this.imageW;
				cy = this.imageY;
				this.initocx = this.imageX;
				this.initocy = this.imageY + this.imageH;
				break;
			case SPDrawAreaImageItem.HANDLE_SW:
				cx = this.imageX;
				cy = this.imageY + this.imageH;
				this.initocx = this.imageX + this.imageW;
				this.initocy = this.imageY;
				break;
		}

		var mpos = this.area.relativeMousePosition(e);

		this.dx = cx - mpos.x;
		this.dy = cy - mpos.y;
		
		e.stop();
		return false;
	},

	updateResize: function(e) {
		var mpos = this.area.relativeMousePosition(e);
		var cx = mpos.x + this.dx, cy = mpos.y + this.dy;
		var tx, ty;
		
		switch (this.resizeDir) {
			case SPDrawAreaImageItem.HANDLE_SE:
				tx = cx - this.imageX;
				ty = cy - this.imageY;

				if (Math.abs(tx) / Math.abs(ty) < this.imageRatio) {
					// fix bottom edge to cursor
					this.imageH = cy - this.imageY;
					this.imageW = this.imageH * this.imageRatio;
				} else {
					// fix right edge to cursor
					this.imageW = cx - this.imageX;
					this.imageH = this.imageW / this.imageRatio;
				}
				break;
			case SPDrawAreaImageItem.HANDLE_NW:
				tx = this.imageX + this.imageW - cx;
				ty = this.imageY + this.imageH - cy;

				if (Math.abs(tx) / Math.abs(ty) < this.imageRatio) {
					// fix top edge to cursor
					this.imageY = cy;
					this.imageH = this.initocy - this.imageY;
					this.imageW = Math.floor(this.imageH * this.imageRatio);
					this.imageX = this.initocx - this.imageW;
				} else {
					// fix left edge to cursor
					this.imageX = cx;
					this.imageW = this.initocx - this.imageX;
					this.imageH = Math.floor(this.imageW / this.imageRatio);
					this.imageY = this.initocy - this.imageH;
				}
				break;
			case SPDrawAreaImageItem.HANDLE_NE:
				tx = cx - this.imageX;
				ty = cy - (this.imageY + this.imageH);

				if (Math.abs(tx) / Math.abs(ty) > this.imageRatio) {
					// fix right edge to cursor
					this.imageW = cx - this.imageX;
					this.imageH = Math.floor(this.imageW / this.imageRatio);
					this.imageY = this.initocy - this.imageH;
				} else {
					// fix top edge to cursor
					this.imageY = cy;
					this.imageH = this.initocy - this.imageY;
					this.imageW = this.imageH * this.imageRatio;
					this.imageX = this.initocx;
				}
				break;
			case SPDrawAreaImageItem.HANDLE_SW:
				tx = this.imageX - cx;
				ty = this.imageY + this.imageH - cy;

				if (Math.abs(tx) / Math.abs(ty) < this.imageRatio) {
					// fix left edge to cursor
					this.imageX = cx;
					this.imageW = this.initocx - this.imageX;
					this.imageH = Math.floor(this.imageW / this.imageRatio);
				} else {
					// fix bottom edge to cursor
					this.imageH = cy - this.imageY;
					this.imageW = Math.floor(this.imageH * this.imageRatio);
					this.imageX = this.initocx - this.imageW;
				}
				break;
		}

		//this.imageX = Math.min(Math.max(this.x + this.w - this.imageW, this.imageX), this.x);
		//this.imageY = Math.min(Math.max(this.y + this.h - this.imageH, this.imageY), this.y);
		
		this._limitPosition();
		
		this.updatePosition();

		return false;
	},

	_limitPosition: function() {
		this.imageX = Math.min(this.x, this.imageX);
		this.imageY = Math.min(this.y, this.imageY);
		
		if (this.imageW < this.x - this.imageX + this.w) {
			this.imageW = this.x - this.imageX + this.w;
			this.imageH = this.imageW / this.imageRatio;
		}

		if (this.imageH < this.y - this.imageY + this.h) {
			this.imageH = this.y - this.imageY + this.h;
			this.imageW = this.imageH * this.imageRatio;
		}
	},

	endResize: function(e) {
		ldocument.detachEvent("mousemove", this, this.updateResize);
		ldocument.detachEvent("mouseup", this, this.endResize);

		this.mode = SPDrawAreaImageItem.MODE_NONE;

		return false;
	},

	beginDrag: function(e) {
		if (this.mode != SPDrawAreaImageItem.MODE_NONE) {
			return false;
		}

		this.mode = SPDrawAreaImageItem.MODE_DRAG;
		
		var mpos = this.area.relativeMousePosition(e);
		this.dx = this.imageX - mpos.x;
		this.dy = this.imageY - mpos.y;
		//alert(this.area.x + " " + this.x + " " + mpos.x);
		//alert(this.dx);

		ldocument.attachEvent("mousemove", this, this.updateDrag);
		ldocument.attachEvent("mouseup", this, this.endDrag);

		return false;
	},

	updateDrag: function(e) {
		var mpos = this.area.relativeMousePosition(e);

		this.imageX = Math.min(Math.max(this.x + this.w - this.imageW, mpos.x + this.dx), this.x);
		this.imageY = Math.min(Math.max(this.y + this.h - this.imageH, mpos.y + this.dy), this.y);

		this.updatePosition();

		return false;
	},

	endDrag: function(e) {
		this.updateDrag(e);

		ldocument.detachEvent("mousemove", this, this.updateDrag);
		ldocument.detachEvent("mouseup", this, this.endDrag);

		this.mode = SPDrawAreaImageItem.MODE_NONE;

		return false;
	},

	zoomBy: function(factor) {
		var newH = Math.floor(this.imageH * factor);
		var newW = Math.floor(newH * this.imageRatio);
		
		this.imageX = Math.floor(this.imageX + (this.imageW - newW) * 0.5);
		this.imageY = Math.floor(this.imageY + (this.imageH - newH) * 0.5);
		
		this.imageW = newW;
		this.imageH = newH;

		this._limitPosition();

		this.updatePosition();
	}
}, {
	HANDLE_NE: 0,
	HANDLE_SE: 1,
	HANDLE_SW: 2,
	HANDLE_NW: 3,

	MODE_NONE: 0,
	MODE_DRAG: 1,
	MODE_RESIZE: 2
});

var preview_popup_timer = null;

function preview_popup_show(el) {
    preview_popup_over();
    $(el).style().display = "block";
}

function preview_popup_hide(el) {
    preview_popup_timer = setTimeout(function() {
        $(el).style().display = "none";
        preview_popup_timer = null;
    }, 10);
}

function preview_popup_over() {
    if (preview_popup_timer) {
        clearTimeout(preview_popup_timer);
        preview_popup_timer = null;
    }
}
