/* 2010 0x2620.org GPL v3 TODO: migrate to ox.js (& sorry for the mess) */ $(function() { if ($.browser.msie) { alert("Please use Firefox, Safari or Chrome."); return; } var $body = $("body"), $document = $(document), $window = $(window), $album = $("#album"), json, users = [], albums = {}, split = location.hash.substr(1).replace("_", " ").split("/"), user = split[0] || "S", album = split[1] || "Beirut", photoid = split[2] || "", hash = photoid ? [user, album, photoid].join("/") : [user, album].join("/"), windowWidth = $window.width(), windowHeight = $window.height() - 24, windowRatio = windowWidth / windowHeight, photo = -1, photos = [], thumbnails = [], playInterval, buttonTimeout, $layer, spinner; location.hash = hash; $.each(["Loading", "Close", "Previous", "Play", "Pause", "Next", "ZoomIn", "ZoomOut"], function(i, name) { $("").attr({ src: "png/symbol" + name + ".png" }); }); function Album(username, albumname) { var that = this, data = json[username][albumname]; that.show = function() { playInterval && $("#play").trigger("click"); $("#zoomin").attr("src") == "png/symbolZoomOut.png" && $("#zoomin").trigger("click"); $(".photo") && $("#close").trigger("click"); $album.empty(); album = albumname; photos = []; photo = -1; $.each(data, function(i, image) { photos[i] = image, thumbnails[i] = new Thumbnail(i).show(); }); $("
").attr({clear: "all"}).appendTo($album); $("
") .css({ height: "24px" }) .appendTo($album); $interface = $("
") .attr({ id: "interface" }) .appendTo($album); $layer = $("
") .attr({ id: "layer" }) .appendTo($album); setTimeout(function() { location.hash = [user, album.replace(" ", "_")].join("/"); }, 500); return that; } return that; } function Button(photo, name, tooltip) { var that = this, $div = $("
") .addClass("button") .mouseenter(showTooltip) .mouseleave(hideTooltip) .click(function() { hideTooltip(); photo.click(name); }), $img = $("") .addClass("button") .attr({ id: name.toLowerCase().replace(" ", ""), src: "png/symbol" + name.replace(" ", "") + ".png", }) .appendTo($div), $tooltip; function hideTooltip() { $tooltip.animate({ opacity: 0 }, 50, function() { $tooltip.remove(); }); } function showTooltip() { $tooltip.html(that.tooltip).appendTo($body).animate({ opacity: 1 }, 50); } that.tooltip = tooltip; that.show = function() { $div.appendTo("#buttons"); $tooltip = $("
") .addClass("tooltip") .css({ left: ($div.offset().left - 52) + "px" }); } return that; } function Dialog(title, text, buttons) { var that = this, $div = $("
") .addClass("background"); $dialog = $("
") .addClass("dialog") .appendTo($div); $title = $("
") .addClass("title") .html(title) .appendTo($dialog); $text = $("
") .addClass("text") .html(text) .appendTo($dialog); $buttons = $("
") .addClass("buttons") .appendTo($dialog); new Input("Close", function() { that.close(); }, $buttons).show(); that.close = function() { $div.animate({ opacity: 0 }, 250, function() { $div.remove(); }); $dialog.animate({ opacity: 0 }, 250); return that; } that.open = function() { $div.appendTo($body).animate({ opacity: 1 }, 250); $dialog.animate({ opacity: 1 }, 250); return that; } return that; } function Input(name, fn, $parent) { var that = this, $parent = $parent || $("#right"), $div = $("
") .addClass("input") .html(name) .click(fn); that.show = function() { $parent.append($div); return that; } return that; } function Map() { var that = this, offset = $(".original").offset(), // fixme: needed? thumbnailWidth = 90 * photos[photo].width / photos[photo].height, thumbnailHeight = 90, boxWidth = thumbnailWidth / photos[photo].width * windowWidth, boxHeight = thumbnailHeight / photos[photo].height * windowHeight, $div = $("
") .addClass("map") .css({ width: thumbnailWidth + "px" }), $img = $("") .addClass("map") .attr({ src: photos[photo].file.replace("/IMG", "/90/IMG"), }) .css({ width: thumbnailWidth + "px" }) .appendTo($div), $interface = $("
") .addClass("interface") .css({ width: thumbnailWidth + "px" }) .click(function(e) { var offset = $div.offset(), left = Math.min(Math.max(e.clientX - offset.left - boxWidth / 2 - 2, 0), thumbnailWidth - boxWidth), top = Math.min(Math.max(e.clientY - offset.top + $body.scrollTop() - boxHeight / 2 - 2, 0), thumbnailHeight - boxHeight); $(".original").animate({ left: -(left * photos[photo].width / thumbnailWidth) + "px", top: -(top * photos[photo].height / thumbnailHeight) + "px" }, 250, function() { that.update(true); }); }) .appendTo($div); $box = $("
") .addClass("box") .css({ width: boxWidth + "px", height: boxHeight + "px" }) .mousedown(function(e) { var left = parseInt($box.css("left")) + 2, top = parseInt($box.css("top")) + 2, x = e.clientX, y = e.clientY; $window.mousemove(function(e) { left = Math.min(Math.max(left + e.clientX - x, 0), thumbnailWidth - boxWidth); top = Math.min(Math.max(top + e.clientY - y, 0), thumbnailHeight - boxHeight); x = e.clientX; y = e.clientY; $(".original").css({ left: -(left * photos[photo].width / thumbnailWidth) + "px", top: -(top * photos[photo].height / thumbnailHeight) + "px" }); that.update(); }); $window.mouseup(function() { $window.unbind("mousemove"); }); }) .appendTo($div); that.show = function() { $div.appendTo($album); that.update(); return that; } that.update = function(animate) { var left = -parseInt($(".original").css("left")) * thumbnailWidth / photos[photo].width - 2, top = -parseInt($(".original").css("top")) * thumbnailHeight / photos[photo].height - 2; if (animate) { $box.animate({ left: left + "px", top: top + "px" }, 250); } else { $box.css({ left: left + "px", top: top + "px" }); } } return that; } function Photo(i) { var that = this, image = photos[i], id = image.file.substr(-8, 4), title = image.file.substr(4, 8), // fixme: needed? zoomedIn = false, keepVisible = false, $buttons = $("
") .attr({ id: "buttons" }) .mouseenter(function() { //console.log("mouseenter") clearTimeout(buttonTimeout); keepVisible = true; }) .mouseleave(function() { buttonTimeout = setTimeout(hideButtons, 2500); keepVisible = false; }) .appendTo($body), map; $img = $("") .addClass("photo") .attr({ src: image.file.replace("/IMG", "/90/IMG"), }); $.each([ ["Close", "CLOSE [ESCAPE]"], ["Previous", "PREVIOUS [LEFT]"], ["Play", "PLAY/PAUSE [SPACE]"], ["Next", "NEXT [RIGHT]"], ["Zoom In", "ZOOM [=/-]"] ], function(i, button) { new Button(that, button[0], button[1]).show(); }); function getOriginalCSS(i) { return { width: photos[i].width + "px", height: photos[i].height + "px" }; } function getPhotoCSS(i) { var size = getSize(i); return { left: ((windowWidth - size.width) / 2) + "px", top: ((windowHeight - size.height) / 2) + "px", width: size.width + "px", height: size.height + "px" }; } function getSize(i) { var photoRatio = photos[i].width / photos[i].height; return { width: windowRatio > photoRatio ? windowHeight * photoRatio : windowWidth, height: windowRatio > photoRatio ? windowHeight : windowWidth / photoRatio }; } function hideButtons() { return; //console.log("hideButtons") $("#buttons").animate({ opacity: 0 }, 250); } function showButtons() { //console.log("showButtons") clearTimeout(buttonTimeout); $("#buttons").animate({ opacity: 1 }, 250); buttonTimeout = setTimeout(hideButtons, 2500); } that.click = function(button) { //console.log("click " + button) if (button == "Close") { that.close(); } else if (button == "Previous") { photo = photo == 0 ? photos.length - 1 : photo - 1; that.show(photo); playInterval && updateInterval(); } else if (button == "Play") { if (!playInterval) { $("#play").attr({ src: "png/symbolPause.png" }); playInterval = setInterval(function() { $("#next").trigger("click"); }, 5000); setTimeout(function() { $("#next").trigger("click"); }, 500); } else { $("#play").attr({ src: "png/symbolPlay.png" }); clearInterval(playInterval); playInterval = 0; } } else if (button == "Next") { photo = photo == photos.length - 1 ? 0 : photo + 1; that.show(photo); playInterval && updateInterval(); } else if (button == "Zoom In") { var left = (photos[photo].width - windowWidth) / -2, top = (photos[photo].height - windowHeight) / -2, x, y; if (!zoomedIn) { zoomedIn = true; spinner = new Spinner().start(); var $img_ = $("") .attr({ src: photos[photo].file }) .load(function() { $img.attr({ src: photos[photo].file }); spinner.stop(); }); $img .animate({ width: photos[photo].width, height: photos[photo].height, left: left, top: top }, 250, function() { $("#zoomin").attr({ src: "png/symbolZoomOut.png" }); $img.addClass("original"); $interface .show() .mousedown(function(e) { left = parseInt($img.css("left")); top = parseInt($img.css("top")); x = e.clientX; y = e.clientY; $window.mousemove(function(e) { left = Math.max(Math.min(left + e.clientX - x, 0), windowWidth - photos[photo].width); top = Math.max(Math.min(top + e.clientY - y, 0), windowHeight - photos[photo].height); x = e.clientX; y = e.clientY; $img.css({ left: left + "px", top: top + "px" }); map.update(); }); $window.mouseup(function() { $window.unbind("mousemove"); }); }); map = new Map().show(); }); } else { zoomedIn = false; $(".map").remove(); $interface.hide(); spinner = new Spinner().start(); var $img_ = $("") .attr({ src: photos[photo].file.replace("/IMG", "/720/IMG") }) .load(function() { $img.attr({ src: photos[photo].file.replace("/IMG", "/720/IMG") }); spinner.stop(); }); $img.animate(getPhotoCSS(photo), 250, function() { $("#zoomin").attr({ src: "png/symbolZoomIn.png" }); }); } } function updateInterval() { clearInterval(playInterval); playInterval = setInterval(function() { $("#next").trigger("click"); }, 5000); } return that; } that.close = function() { var thumbnailPosition = thumbnails[photo].position(); if (playInterval) { $("#play").trigger("click"); } $("#buttons").remove(); $(".map").remove(); $img.animate({ left: thumbnailPosition.left, top: thumbnailPosition.top, width: thumbnailPosition.width, height: thumbnailPosition.height }, 250, function() { location.hash = [user, album].join("/"); $img.unbind("mouseenter"); $img.unbind("mouseleave"); $img.unbind("mousemove"); $img.remove(); }); $layer.animate({ opacity: 0 }, 250, function() { $layer.hide(); }); spinner.stop(); $interface.hide(); $document.unbind("keydown"); return that; } that.open = function() { var thumbnailPosition = thumbnails[i].position(); $img.css({ left: thumbnailPosition.left, top: thumbnailPosition.top, width: thumbnailPosition.width, height: thumbnailPosition.height }) .appendTo($album) .animate(getPhotoCSS(i), 250, function() { location.hash = [user, album, id].join("/"); spinner = new Spinner().start(); var $img_ = $("") .attr({ src: photos[i].file.replace("/IMG", "/720/IMG") }) .load(function() { $img.attr({ src: photos[i].file.replace("/IMG", "/720/IMG") }); spinner.stop(); }); /* $img.mouseenter(showButtons) .mouseleave(hideButtons) .mousemove(function() { if (!keepVisible) { showButtons(); } }); */ showButtons(); $document.keydown(function(e) { //console.log(e.keyCode); var d = 0; if (photo > -1) { if (e.keyCode == 27) { $("#close").trigger("click"); } else if (e.keyCode == 32) { showButtons(); $("#play").trigger("click"); } else if (e.keyCode == 37) { showButtons(); $("#previous").trigger("click"); } else if (e.keyCode == 39) { showButtons(); $("#next").trigger("click"); } else if (e.keyCode == 187) { showButtons(); !zoomedIn && $("#zoomin").trigger("click"); } else if (e.keyCode == 189) { showButtons(); zoomedIn && $("#zoomin").trigger("click"); } } }); }); $layer.show().animate({ opacity: 1 }, 250); photo = i; return that; } that.remove = function() { $img.remove(); return that; } that.show = function(i) { var $imgOld = $img, offset = $img.offset(), size = { width: $img.width(), height: $img.height() }; $img = $("") .addClass(zoomedIn ? "original" : "photo") .attr({ src: photos[i].file.replace("/IMG", "/90/IMG"), }) .css(zoomedIn ? $.extend(getOriginalCSS(i), { left: offset.left + "px", top: offset.top + "px" }) : getPhotoCSS(i)) .css({ opacity: 0 }) .appendTo($album) .animate({ opacity: 1 }, playInterval ? 500 : 250, function() { location.hash = [user, album, photos[i].file.substr(-8, 4)].join("/"); $imgOld.remove(); photo = i; if (zoomedIn) { if (photos[i].width / size.width == size.width && photos[i].height == size.height) { $("img.map") .attr({ src: photos[photo].file.replace("/IMG", "/90/IMG"), }); } else { $img.css({ left: offset.left * (photos[i].width - windowWidth) / (size.width - windowWidth), top: offset.top * (photos[i].height - windowHeight) / (size.height - windowHeight) }); $("div.map").remove(); map = new Map().show(); } } }); spinner = new Spinner().start(); var $img_ = $("") .attr({ src: photos[photo].file.replace("/IMG", "/720/IMG") }) .load(function() { $img.attr({ src: photos[photo].file.replace("/IMG", "/720/IMG") }); if (zoomedIn) { $img_ = $("") .attr({ src: photos[photo].file }) .load(function() { $img.attr({ src: photos[photo].file }); spinner.stop(); }); } else { spinner.stop(); } }); return that; } return that; } function Select(name, options, selected) { var that = this, $div = $("
") .addClass("select"); $val = $("
") .html(name + ": " + selected) .appendTo($div); $select = $("