2012-01-11 17:04:20 +01:00
|
|
|
$(document).ready(function() {
|
2012-01-16 10:22:22 +01:00
|
|
|
// Handlers for showing/hiding the upload dialog via clicks & keys.
|
2012-01-11 17:04:20 +01:00
|
|
|
$("#add").click(show_add_dialog);
|
|
|
|
$("#add_form #cancel").click(hide_add_dialog);
|
2012-01-12 13:22:52 +01:00
|
|
|
if ($.browser.mozilla) {
|
|
|
|
$(document).keypress(key_handler);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$(document).keyup(key_handler);
|
|
|
|
}
|
2012-01-11 23:31:07 +01:00
|
|
|
|
2012-01-16 10:22:22 +01:00
|
|
|
// The plempable jQuery plugin containing most of the Plemp! UI
|
|
|
|
// functionality.
|
|
|
|
$.fn.plempable = function(data) {
|
2012-02-14 18:49:47 +01:00
|
|
|
var type = data.mime.split("/")[0];
|
2012-01-16 10:22:22 +01:00
|
|
|
this.draggable({ stack: ".draggable",
|
|
|
|
containment: "window",
|
2012-01-17 14:27:37 +01:00
|
|
|
cancel: "audio, video",
|
|
|
|
distance: 10,
|
2012-01-16 10:22:22 +01:00
|
|
|
stop: update_drag_info })
|
2012-02-14 18:49:47 +01:00
|
|
|
.click(raise_draggable);
|
|
|
|
// Make it resizable with parameters based on the type:
|
|
|
|
// FIXME: is there a better way than repeating the common options?
|
|
|
|
switch(type) {
|
|
|
|
case "image":
|
|
|
|
case "video":
|
|
|
|
this.resizable({ distance: 10,
|
|
|
|
start: raise_draggable,
|
|
|
|
stop: update_drag_info,
|
|
|
|
handles: "se",
|
|
|
|
minHeight: 250,
|
|
|
|
aspectRatio: true });
|
|
|
|
break;
|
|
|
|
case "audio":
|
|
|
|
this.resizable({ distance: 10,
|
|
|
|
start: raise_draggable,
|
|
|
|
stop: update_drag_info,
|
|
|
|
handles: "e",
|
|
|
|
minWidth: 300 });
|
|
|
|
break;
|
|
|
|
case "text":
|
|
|
|
case "application":
|
|
|
|
this.resizable({ distance: 10,
|
|
|
|
start: raise_draggable,
|
|
|
|
stop: update_drag_info,
|
|
|
|
handles: "se",
|
|
|
|
minWidth: 300,
|
|
|
|
minHeight: 150,
|
|
|
|
alsoResize: "#" + this.attr("id") + " pre" });
|
|
|
|
}
|
|
|
|
// Configure events for child elements.
|
2012-02-11 12:32:36 +01:00
|
|
|
this.find(".download").click({ id: this.attr("id") }, download_draggable);
|
2012-02-13 18:07:11 +01:00
|
|
|
this.find(".delete").click({ id: this.attr("id") }, confirm_delete_draggable);
|
2012-01-16 20:27:09 +01:00
|
|
|
this.find(".title").editable('draggables/' + this.attr("id"),
|
2012-01-16 10:22:22 +01:00
|
|
|
{ tooltip: "Click to edit…",
|
|
|
|
name: 'title',
|
|
|
|
submit: 'OK',
|
2012-01-17 14:27:37 +01:00
|
|
|
cancel: 'Cancel',
|
2012-01-16 10:22:22 +01:00
|
|
|
style: 'inherit' });
|
|
|
|
// FIXME: actually get the comments!
|
2012-02-14 18:48:02 +01:00
|
|
|
//this.find(".comments").text("Comments (0)");
|
|
|
|
// Fix the height of the pre block. FIXME: can this be improved?
|
|
|
|
this.find("pre").css({ height: (this.height() - 80) + "px" });
|
|
|
|
// Highlight contained code in the pre block.
|
2012-01-16 10:22:22 +01:00
|
|
|
this.find("pre code").each(function(idx, elem) {
|
|
|
|
hljs.highlightBlock(elem, ' ');
|
|
|
|
});
|
2012-02-11 12:30:01 +01:00
|
|
|
return $(this);
|
2012-01-16 10:22:22 +01:00
|
|
|
};
|
|
|
|
|
2012-02-13 18:07:11 +01:00
|
|
|
// Set up the dialogs.
|
|
|
|
$("#add_dialog").dialog({ autoOpen: false,
|
|
|
|
width: "auto",
|
|
|
|
show: "fade",
|
|
|
|
hide: "fade",
|
|
|
|
resizable: false,
|
|
|
|
modal: true,
|
|
|
|
close: clear_add_dialog_form,
|
|
|
|
buttons: { "Cancel": hide_add_dialog,
|
|
|
|
"Upload!": function() {
|
|
|
|
$("#add_form")[0].submit();
|
|
|
|
}}});
|
|
|
|
$("#delete_confirm").dialog({ autoOpen: false,
|
|
|
|
show: "fade",
|
|
|
|
hide: "fade",
|
|
|
|
resizable: false,
|
|
|
|
buttons: { "Cancel": function() {
|
|
|
|
$(this).dialog("close");
|
|
|
|
},
|
|
|
|
"Delete": function() {
|
|
|
|
$(this).dialog("close");
|
|
|
|
delete_draggable($(this).data("id"));
|
|
|
|
}}});
|
|
|
|
|
2012-01-18 22:12:03 +01:00
|
|
|
// For drag & drop file uploading via the filedrop jQuery plugin and HTML5.
|
2012-02-13 18:07:11 +01:00
|
|
|
$("body").filedrop({ url: '/draggables',
|
2012-01-18 22:12:03 +01:00
|
|
|
paramname: 'file',
|
|
|
|
data: { type: 'dnd' },
|
|
|
|
maxfiles: 1,
|
|
|
|
maxfilesize: 50,
|
2012-02-14 00:25:29 +01:00
|
|
|
error: handle_filedrop_error
|
2012-01-18 22:12:03 +01:00
|
|
|
});
|
|
|
|
|
2012-01-12 13:22:52 +01:00
|
|
|
// Populate the canvas with the draggables.
|
2012-01-12 11:38:40 +01:00
|
|
|
$.get("draggables", function(data) {
|
2012-02-09 10:28:09 +01:00
|
|
|
var timestamp = data.timestamp;
|
|
|
|
|
|
|
|
// Retrieve each draggable from the list and add it to the canvas.
|
|
|
|
$.each(data.list, function(drag_id, drag_info) {
|
|
|
|
add_draggable_to_canvas(drag_id, drag_info);
|
2012-01-16 10:22:22 +01:00
|
|
|
});
|
2012-02-09 10:31:03 +01:00
|
|
|
|
|
|
|
// Start a (long-poll) loop for update events from the server.
|
|
|
|
poll_server(timestamp);
|
2012-01-11 23:31:07 +01:00
|
|
|
}, "json");
|
2012-01-11 17:04:20 +01:00
|
|
|
});
|
|
|
|
|
2012-02-09 10:28:09 +01:00
|
|
|
// Callback functions
|
2012-01-16 10:22:22 +01:00
|
|
|
|
2012-02-13 18:07:11 +01:00
|
|
|
// Clear the form of the add dialog.
|
|
|
|
function clear_add_dialog_form() {
|
|
|
|
$("#add_form")[0].reset();
|
|
|
|
}
|
|
|
|
|
2012-01-16 10:22:22 +01:00
|
|
|
// Show the add dialog with a visual effect.
|
2012-01-11 17:04:20 +01:00
|
|
|
function show_add_dialog() {
|
2012-02-13 18:07:11 +01:00
|
|
|
$("#add_dialog").dialog("open");
|
2012-01-15 17:15:10 +01:00
|
|
|
}
|
2012-01-11 17:04:20 +01:00
|
|
|
|
2012-01-16 10:22:22 +01:00
|
|
|
// Hide the add dialog with a visual effect and reset the form when finished.
|
2012-01-11 17:04:20 +01:00
|
|
|
function hide_add_dialog() {
|
2012-02-13 18:07:11 +01:00
|
|
|
$("#add_dialog").dialog("close");
|
2012-01-15 17:15:10 +01:00
|
|
|
}
|
|
|
|
|
2012-02-09 10:28:09 +01:00
|
|
|
// Add a draggable element to the canvas.
|
|
|
|
function add_draggable_to_canvas(drag_id, drag_info) {
|
2012-02-11 23:56:40 +01:00
|
|
|
$.get("draggables/" + drag_id, function(data) {
|
|
|
|
$("#draggables").append(data);
|
|
|
|
// Assume we have appended a signle draggable here:
|
|
|
|
$(".draggable").last().plempable(drag_info).fadeIn('slow');
|
|
|
|
});
|
2012-02-09 10:28:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Delete a draggable element from the canvas.
|
|
|
|
function delete_draggable_from_canvas(drag_id) {
|
|
|
|
$("#draggables #" + drag_id).hide('fade', 'slow', function() {
|
2012-02-13 18:07:11 +01:00
|
|
|
$(this).remove();
|
2012-02-09 10:28:09 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2012-02-13 18:07:11 +01:00
|
|
|
// Confirm the deletion of the draggable using the confirm dialog.
|
|
|
|
function confirm_delete_draggable(event) {
|
|
|
|
event.preventDefault();
|
|
|
|
$("#delete_confirm").data("id", event.data.id)
|
|
|
|
.dialog("open");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Deletion has been confirmed, delete the draggable from the server and
|
|
|
|
// then the canvas.
|
|
|
|
function delete_draggable(drag_id) {
|
2012-01-15 17:15:10 +01:00
|
|
|
$.post("draggables/" + drag_id, {"_method": "delete"}, function(data) {
|
2012-02-13 18:07:11 +01:00
|
|
|
if (data) delete_draggable_from_canvas(drag_id);
|
2012-01-15 17:15:10 +01:00
|
|
|
}, "json");
|
|
|
|
}
|
2012-01-11 23:31:07 +01:00
|
|
|
|
2012-02-11 12:32:36 +01:00
|
|
|
// Download a draggable from the server.
|
|
|
|
function download_draggable(event) {
|
|
|
|
event.preventDefault();
|
|
|
|
window.open("download/" + event.data.id);
|
|
|
|
}
|
|
|
|
|
2012-01-17 14:27:52 +01:00
|
|
|
// Raise the draggable to the foreground.
|
|
|
|
function raise_draggable(event) {
|
|
|
|
var max = 0;
|
|
|
|
$(".draggable").each(function() {
|
|
|
|
var cur = parseFloat($(this).css("z-index"));
|
|
|
|
max = cur > max ? cur : max;
|
|
|
|
});
|
|
|
|
$(this).css("z-index", max + 1);
|
|
|
|
}
|
|
|
|
|
2012-01-16 10:22:22 +01:00
|
|
|
// Update the position of a draggable on the server.
|
2012-01-11 23:31:07 +01:00
|
|
|
function update_drag_info(event, ui) {
|
2012-02-14 18:50:49 +01:00
|
|
|
if (ui.size) {
|
|
|
|
$.post("draggables/" + ui.helper.context.id, ui.size, "json");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$.post("draggables/" + ui.helper.context.id, ui.position, "json");
|
|
|
|
}
|
2012-01-11 23:31:07 +01:00
|
|
|
}
|
2012-01-12 13:22:52 +01:00
|
|
|
|
2012-02-09 10:31:03 +01:00
|
|
|
// Poll for server events via AJAX.
|
|
|
|
function poll_server(timestamp) {
|
|
|
|
$.ajax({ url: "events?timestamp=" + timestamp,
|
|
|
|
success: handle_server_event,
|
|
|
|
error: function() { poll_server(timestamp) }, // FIXME; handle properly!
|
|
|
|
dataType: "json", timeout: 60000 });
|
|
|
|
};
|
|
|
|
|
2012-02-14 00:25:29 +01:00
|
|
|
// Handle server events.
|
2012-02-09 10:31:03 +01:00
|
|
|
function handle_server_event(event) {
|
2012-02-14 18:50:49 +01:00
|
|
|
var drag = $("#draggables #" + event.data.id);
|
2012-02-09 10:31:03 +01:00
|
|
|
switch(event.type) {
|
|
|
|
case "reposition":
|
2012-02-14 18:50:49 +01:00
|
|
|
drag.animate({ top: event.data.top, left: event.data.left });
|
|
|
|
break;
|
|
|
|
case "resize":
|
|
|
|
drag.animate({ width: event.data.width, height: event.data.height })
|
|
|
|
// Fix the height of the pre. FIXME: can this be improved?
|
|
|
|
.find("pre").animate({ height: event.data.height - 80 });
|
2012-02-09 10:31:03 +01:00
|
|
|
break;
|
|
|
|
case "title update":
|
|
|
|
$("#draggables #" + event.data.id + " h2 .title").text(event.data.title);
|
|
|
|
break;
|
|
|
|
case "add":
|
|
|
|
add_draggable_to_canvas(event.data.id, event.data.info);
|
|
|
|
break;
|
|
|
|
case "delete":
|
|
|
|
delete_draggable_from_canvas(event.data.id);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
console.log("Unsupported event type!");
|
|
|
|
console.log(event);
|
|
|
|
}
|
|
|
|
poll_server(event.timestamp);
|
|
|
|
}
|
|
|
|
|
2012-02-14 00:25:29 +01:00
|
|
|
// Handle filedrop (drag & drop uploading) errors.
|
|
|
|
function handle_filedrop_error(err, file) {
|
|
|
|
switch(err) {
|
|
|
|
case 'BrowserNotSupported':
|
|
|
|
flash_message("Your browser does not support drag & drop! " +
|
|
|
|
"Please click this button to upload:");
|
|
|
|
break;
|
|
|
|
case 'TooManyFiles':
|
|
|
|
// user uploaded more than 'maxfiles'
|
|
|
|
flash_message("You can only upload a single file at once!");
|
|
|
|
break;
|
|
|
|
case 'FileTooLarge':
|
|
|
|
// program encountered a file whose size is greater than 'maxfilesize'
|
|
|
|
// FileTooLarge also has access to the file which was too large
|
|
|
|
// use file.name to reference the filename of the culprit file
|
|
|
|
flash_message("The file is too large! " +
|
|
|
|
"Ensure it is smaller than than 50MB.");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
console.log(err, file);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Flash some messsage.
|
|
|
|
function flash_message(msg) {
|
|
|
|
$("#message").html(msg)
|
|
|
|
$("#message").fadeIn('slow').delay(5000).fadeOut('fast');
|
|
|
|
}
|
|
|
|
|
2012-01-16 10:22:22 +01:00
|
|
|
// Handle the Escape and Plus keys for hiding/showing the add dialog.
|
2012-01-12 13:22:52 +01:00
|
|
|
function key_handler(event) {
|
|
|
|
switch (event.keyCode) {
|
|
|
|
case 27: /* Escape */
|
|
|
|
hide_add_dialog();
|
|
|
|
break;
|
|
|
|
case 187: /* Plus (numpad) */
|
|
|
|
show_add_dialog();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|