memo/client/script.js

874 lines
17 KiB
JavaScript
Raw Normal View History

2011-03-10 08:20:27 -05:00
var cards = {};
var totalcolumns = 0;
var columns = [];
2011-03-12 13:40:44 -05:00
var currentTheme = "bigcards";
2011-05-29 15:36:30 -04:00
var boardInitialized = false;
var keyTrap = null;
2011-03-10 08:20:27 -05:00
var socket = io.connect();
2011-03-10 08:20:27 -05:00
//an action has happened, send it to the
//server
function sendAction(a, d)
{
//console.log('--> ' + a);
var message = {
2011-03-10 08:20:27 -05:00
action: a,
data: d
}
socket.json.send ( message );
2011-03-10 08:20:27 -05:00
}
socket.on('connect', function(){
2011-03-10 08:20:27 -05:00
//console.log('successful socket.io connect');
2011-03-10 08:20:27 -05:00
//let the path be the room name
var path = location.pathname;
2011-03-10 08:20:27 -05:00
//imediately join the room which will trigger the initializations
sendAction('joinRoom', path);
})
socket.on('disconnect', function(){
2011-05-29 15:36:30 -04:00
blockUI("Server disconnected. Refresh page to try and reconnect...");
//$('.blockOverlay').click($.unblockUI);
2011-03-10 08:20:27 -05:00
});
socket.on('message', function(data){
2011-03-10 08:20:27 -05:00
getMessage(data);
})
2011-05-29 15:36:30 -04:00
function unblockUI()
{
$.unblockUI();
}
function blockUI(message)
{
message = message || 'Waiting...';
$.blockUI({
2011-05-29 15:36:30 -04:00
message: message,
css: {
border: 'none',
padding: '15px',
backgroundColor: '#000',
'-webkit-border-radius': '10px',
'-moz-border-radius': '10px',
opacity: .5,
color: '#fff',
2011-05-29 15:36:30 -04:00
fontSize: '20px'
}
});
2011-05-29 15:36:30 -04:00
}
2011-03-10 08:20:27 -05:00
//respond to an action event
function getMessage( m )
{
var message = m; //JSON.parse(m);
var action = message.action;
var data = message.data;
2011-03-10 08:20:27 -05:00
//console.log('<-- ' + action);
2011-03-10 08:20:27 -05:00
switch (action)
{
case 'roomAccept':
//okay we're accepted, then request initialization
//(this is a bit of unnessary back and forth but that's okay for now)
sendAction('initializeMe', null);
break;
2011-03-10 08:20:27 -05:00
case 'roomDeny':
//this doesn't happen yet
break;
2011-03-10 08:20:27 -05:00
case 'moveCard':
moveCard($("#" + data.id), data.position);
2011-03-10 08:20:27 -05:00
break;
2011-03-10 08:20:27 -05:00
case 'initCards':
initCards(data);
break;
2011-03-10 08:20:27 -05:00
case 'createCard':
//console.log(data);
drawNewCard(data.id, data.text, data.x, data.y, data.rot, data.colour, null);
2011-03-10 08:20:27 -05:00
break;
2011-03-10 08:20:27 -05:00
case 'deleteCard':
$("#" + data.id).fadeOut(500,
function() {$(this).remove();}
);
break;
2011-03-10 08:20:27 -05:00
case 'editCard':
$("#" + data.id).children('.content:first').text(data.value);
break;
2011-03-10 08:20:27 -05:00
case 'initColumns':
initColumns(data);
break;
2011-03-10 08:20:27 -05:00
case 'updateColumns':
initColumns(data);
break;
2011-03-10 08:20:27 -05:00
case 'changeTheme':
changeThemeTo(data);
break;
2011-03-10 08:20:27 -05:00
case 'join-announce':
displayUserJoined(data.sid, data.user_name);
break;
2011-03-10 08:20:27 -05:00
case 'leave-announce':
displayUserLeft(data.sid);
break;
2011-03-10 08:20:27 -05:00
case 'initialUsers':
displayInitialUsers(data);
break;
2011-03-10 08:20:27 -05:00
case 'nameChangeAnnounce':
updateName( message.data.sid, message.data.user_name );
break;
2011-03-10 08:20:27 -05:00
case 'addSticker':
addSticker( message.data.cardId, message.data.stickerId );
break;
2011-05-27 01:08:25 -04:00
case 'setBoardSize':
resizeBoard( message.data );
break;
2011-03-10 08:20:27 -05:00
default:
//unknown message
alert('unknown action: ' + JSON.stringify(message));
break;
}
2011-03-10 08:20:27 -05:00
}
$(document).bind('keyup', function(event) {
keyTrap = event.which;
});
2011-03-10 08:20:27 -05:00
function drawNewCard(id, text, x, y, rot, colour, sticker, animationspeed)
2011-03-10 08:20:27 -05:00
{
//cards[id] = {id: id, text: text, x: x, y: y, rot: rot, colour: colour};
var h = '<div id="' + id + '" class="card ' + colour +
' draggable" style="-webkit-transform:rotate(' + rot + 'deg);\
">\
2011-03-10 08:20:27 -05:00
<img src="/images/icons/token/Xion.png" class="card-icon delete-card-icon" />\
<img class="card-image" src="/images/' + colour + '-card.png">\
<div id="content:' + id + '" class="content stickertarget droppable">' +
text + '</div>\
2011-03-10 08:20:27 -05:00
</div>';
2011-06-14 07:42:04 +08:00
var card = $(h);
2011-06-14 07:42:04 +08:00
card.appendTo('#board');
//@TODO
//Draggable has a bug which prevents blur event
//http://bugs.jqueryui.com/ticket/4261
//So we have to blur all the cards and editable areas when
//we click on a card
//The following doesn't work so we will do the bug
//fix recommended in the above bug report
// card.click( function() {
// $(this).focus();
// } );
2011-06-14 07:42:04 +08:00
card.draggable(
{
2011-03-10 08:20:27 -05:00
snap: false,
snapTolerance: 5,
containment: [0,0,2000,2000],
stack: ".card",
start: function (event, ui) {
keyTrap = null;
},
drag: function (event, ui) {
if (keyTrap == 27) {
ui.helper.css(ui.originalPosition);
return false;
}
}
}
2011-03-10 08:20:27 -05:00
);
2011-03-10 08:20:27 -05:00
//After a drag:
2011-06-14 07:42:04 +08:00
card.bind( "dragstop", function(event, ui) {
if (keyTrap == 27) {
keyTrap = null;
return;
}
2011-06-14 07:42:04 +08:00
2011-03-10 08:20:27 -05:00
var data = {
id: this.id,
position: ui.position,
oldposition: ui.originalPosition,
};
2011-03-10 08:20:27 -05:00
sendAction('moveCard', data);
});
2011-06-14 08:21:05 +08:00
card.children(".droppable").droppable(
{
accept: '.sticker',
2011-03-10 08:20:27 -05:00
drop: function( event, ui ) {
var stickerId = ui.draggable.attr("id");
var cardId = $(this).parent().attr('id');
2011-03-10 08:20:27 -05:00
addSticker( cardId, stickerId );
2011-03-10 08:20:27 -05:00
var data = { cardId: cardId, stickerId: stickerId };
sendAction('addSticker', data);
2013-12-08 09:18:41 -05:00
//remove hover state to everything on the board to prevent
//a jquery bug where it gets left around
$('.card-hover-draggable').removeClass('card-hover-draggable');
},
hoverClass: 'card-hover-draggable'
}
2011-03-10 08:20:27 -05:00
);
var speed = Math.floor(Math.random() * 1000);
if (typeof(animationspeed) != 'undefined') speed = animationspeed;
2011-06-14 07:42:04 +08:00
var startPosition = $("#create-card").position();
card.css( 'top' , startPosition.top - card.height()*.5 );
card.css('left', startPosition.left - card.width() *.5 );
2011-06-14 07:42:04 +08:00
card.animate({
2011-03-10 08:20:27 -05:00
left: x + "px",
top: y + "px"
}, speed);
card.hover(
function(){
2011-03-10 08:20:27 -05:00
$(this).addClass('hover');
$(this).children('.card-icon').fadeIn(10);
},
function(){
$(this).removeClass('hover');
$(this).children('.card-icon').fadeOut(150);
}
);
2011-06-14 07:42:04 +08:00
card.children('.card-icon').hover(
2011-03-10 08:20:27 -05:00
function(){
$(this).addClass('card-icon-hover');
},
function(){
$(this).removeClass('card-icon-hover');
}
);
2011-06-14 07:42:04 +08:00
card.children('.delete-card-icon').click(
2011-03-10 08:20:27 -05:00
function(){
$("#" + id).remove();
//notify server of delete
sendAction( 'deleteCard' , { 'id': id });
}
);
card.children('.content').editable(function(value, settings) {
onCardChange( id, value );
return(value);
}, {
type : 'textarea',
submit : 'OK',
style : 'inherit',
cssclass : 'card-edit-form',
type : 'textarea',
placeholder : 'Double Click to Edit.',
onblur: 'submit',
event: 'dblclick', //event: 'mouseover'
});
2011-03-10 08:20:27 -05:00
//add applicable sticker
if (sticker != null)
$("#" + id).children('.content').addClass( sticker );
}
function onCardChange( id, text )
{
2011-03-10 08:20:27 -05:00
sendAction('editCard', { id: id, value: text });
}
2011-06-14 07:42:04 +08:00
function moveCard(card, position) {
card.animate({
left: position.left+"px",
top: position.top+"px"
}, 500);
2011-06-14 07:42:04 +08:00
}
function addSticker ( cardId , stickerId )
2011-03-10 08:20:27 -05:00
{
2011-03-10 08:20:27 -05:00
cardContent = $('#' + cardId).children('.content');
2011-03-10 08:20:27 -05:00
cardContent.removeClass("sticker-red");
cardContent.removeClass("sticker-blue");
cardContent.removeClass("sticker-green");
cardContent.removeClass("sticker-yellow");
cardContent.removeClass("sticker-gold");
cardContent.removeClass("sticker-silverstar");
cardContent.removeClass("sticker-bluestar");
cardContent.removeClass("sticker-redstar");
cardContent.removeClass("sticker-orange");
cardContent.removeClass("sticker-pink");
cardContent.removeClass("sticker-purple");
cardContent.removeClass("sticker-lightblue");
cardContent.addClass( stickerId );
}
//----------------------------------
// cards
//----------------------------------
function createCard( id, text, x, y, rot, colour )
{
drawNewCard(id, text, x, y, rot, colour, null);
2011-03-10 08:20:27 -05:00
var action = "createCard";
2011-03-10 08:20:27 -05:00
var data = {
id: id,
text: text,
x: x,
y: y,
rot: rot,
colour: colour
};
2011-03-10 08:20:27 -05:00
sendAction(action, data);
2011-03-10 08:20:27 -05:00
}
function randomCardColour()
{
var colours = ['yellow', 'green', 'blue', 'white'];
2011-03-10 08:20:27 -05:00
var i = Math.floor(Math.random() * colours.length);
2011-03-10 08:20:27 -05:00
return colours[i];
}
function initCards( cardArray )
{
//first delete any cards that exist
$('.card').remove();
2011-03-10 08:20:27 -05:00
cards = cardArray;
2011-03-10 08:20:27 -05:00
for (i in cardArray)
{
card = cardArray[i];
2011-03-10 08:20:27 -05:00
drawNewCard(
card.id,
card.text,
card.x,
card.y,
card.rot,
card.colour,
card.sticker
);
}
2011-05-29 15:36:30 -04:00
boardInitialized = true;
unblockUI();
2011-03-10 08:20:27 -05:00
}
//----------------------------------
// cols
//----------------------------------
function drawNewColumn (columnName)
{
2011-03-10 08:20:27 -05:00
var cls = "col";
if (totalcolumns == 0)
{
cls = "col first";
}
$('#icon-col').before('<td class="' + cls + '" width="10%" style="display:none"><h2 id="col-' + (totalcolumns+1) + '" class="editable">' + columnName + '</h2></td>');
$('.editable').editable(function(value, settings) {
onColumnChange( this.id, value );
return(value);
}, {
style : 'inherit',
cssclass : 'card-edit-form',
type : 'textarea',
placeholder : 'New',
onblur: 'submit',
width: '',
height: '',
xindicator: '<img src="/images/ajax-loader.gif">',
event: 'dblclick', //event: 'mouseover'
});
2011-03-10 08:20:27 -05:00
$('.col:last').fadeIn(1500);
2011-03-10 08:20:27 -05:00
totalcolumns ++;
}
function onColumnChange( id, text )
2011-03-10 08:20:27 -05:00
{
var names = Array();
//console.log(id + " " + text );
//Get the names of all the columns right from the DOM
2011-03-10 08:20:27 -05:00
$('.col').each(function() {
//get ID of current column we are traversing over
var thisID = $(this).children("h2").attr('id');
if (id == thisID)
{
names.push( text );
}
else
{
names.push( $(this).text() );
}
2011-03-10 08:20:27 -05:00
});
2011-03-10 08:20:27 -05:00
updateColumns(names);
}
function displayRemoveColumn()
{
if (totalcolumns <= 0) return false;
2011-03-10 08:20:27 -05:00
$('.col:last').fadeOut( 150,
function() {
$(this).remove();
}
);
2011-03-10 08:20:27 -05:00
totalcolumns --;
}
function createColumn( name )
{
if (totalcolumns >= 8) return false;
2011-03-10 08:20:27 -05:00
drawNewColumn( name );
columns.push(name);
2011-03-10 08:20:27 -05:00
var action = "updateColumns";
2011-03-10 08:20:27 -05:00
var data = columns;
2011-03-10 08:20:27 -05:00
sendAction(action, data);
}
function deleteColumn()
{
if (totalcolumns <= 0) return false;
2011-03-10 08:20:27 -05:00
displayRemoveColumn();
columns.pop();
2011-03-10 08:20:27 -05:00
var action = "updateColumns";
2011-03-10 08:20:27 -05:00
var data = columns;
2011-03-10 08:20:27 -05:00
sendAction(action, data);
}
function updateColumns( c )
{
columns = c;
2011-03-10 08:20:27 -05:00
var action = "updateColumns";
2011-03-10 08:20:27 -05:00
var data = columns;
2011-03-10 08:20:27 -05:00
sendAction(action, data);
}
function deleteColumns( next )
{
//delete all existing columns:
$('.col').fadeOut( 'slow', next() );
}
function initColumns( columnArray )
{
totalcolumns = 0;
columns = columnArray;
2011-03-10 08:20:27 -05:00
$('.col').remove();
2011-03-10 08:20:27 -05:00
for (i in columnArray)
{
column = columnArray[i];
drawNewColumn(
column
);
}
}
function changeThemeTo( theme )
{
2011-03-12 13:40:44 -05:00
currentTheme = theme;
2011-03-10 08:20:27 -05:00
$("link[title=cardsize]").attr("href", "/css/" + theme + ".css");
}
//////////////////////////////////////////////////////////
////////// NAMES STUFF ///////////////////////////////////
//////////////////////////////////////////////////////////
function setCookie(c_name,value,exdays)
{
var exdate=new Date();
exdate.setDate(exdate.getDate() + exdays);
var c_value=escape(value) + ((exdays==null) ? "" : "; expires="+exdate.toUTCString());
document.cookie=c_name + "=" + c_value;
}
function getCookie(c_name)
{
var i,x,y,ARRcookies=document.cookie.split(";");
for (i=0;i<ARRcookies.length;i++)
{
x=ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
y=ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1);
x=x.replace(/^\s+|\s+$/g,"");
if (x==c_name)
{
return unescape(y);
}
2011-03-10 08:20:27 -05:00
}
}
function setName( name )
{
sendAction( 'setUserName', name );
2011-03-10 08:20:27 -05:00
setCookie('scrumscrum-username', name, 365);
}
function displayInitialUsers (users)
{
for (i in users)
{
//console.log(users);
displayUserJoined(users[i].sid, users[i].user_name);
}
}
function displayUserJoined ( sid, user_name )
{
name = '';
if (user_name)
name = user_name;
else
name = sid.substring(0,5);
2011-03-10 08:20:27 -05:00
$('#names-ul').append('<li id="user-' + sid + '">' + name + '</li>')
}
function displayUserLeft ( sid )
{
name = '';
if (name)
name = user_name;
else
name = sid;
2011-03-10 08:20:27 -05:00
var id = '#user-' + sid.toString();
2011-03-10 08:20:27 -05:00
$('#names-ul').children(id).fadeOut( 1000 , function() {
$(this).remove();
});
}
function updateName ( sid, name )
{
var id = '#user-' + sid.toString();
2011-03-10 08:20:27 -05:00
$('#names-ul').children(id).text( name );
}
2011-05-27 01:08:25 -04:00
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
function boardResizeHappened(event, ui)
{
var newsize = ui.size
2011-06-14 07:42:04 +08:00
2011-05-27 01:08:25 -04:00
sendAction( 'setBoardSize', newsize);
}
function resizeBoard (size) {
$( ".board-outline" ).animate( {
2011-05-27 01:08:25 -04:00
height: size.height,
width: size.width
} );
}
2011-03-10 08:20:27 -05:00
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
2011-06-14 07:42:04 +08:00
function calcCardOffset() {
var offsets = {};
$(".card").each(function() {
var card = $(this);
$(".col").each(function(i) {
var col = $(this);
if(col.offset().left + col.outerWidth() > card.offset().left + card.outerWidth() || i === $(".col").size() - 1) {
offsets[card.attr('id')] = {
col: col,
x: ( (card.offset().left - col.offset().left) / col.outerWidth() )
}
return false;
}
});
});
return offsets;
2011-06-14 07:42:04 +08:00
}
2011-06-23 19:12:53 -04:00
//moves cards with a resize of the Board
//doSync is false if you don't want to synchronize
//with all the other users who are in this room
function adjustCard(offsets, doSync) {
$(".card").each(function() {
2011-06-23 19:12:53 -04:00
var card = $(this);
var offset = offsets[this.id];
if(offset) {
var data = {
id: this.id,
position: {
left: offset.col.position().left + (offset.x * offset.col.outerWidth()),
top: parseInt(card.css('top').slice(0,-2))
},
oldposition: {
left: parseInt(card.css('left').slice(0,-2)),
top: parseInt(card.css('top').slice(0,-2))
}
}; //use .css() instead of .position() because css' rotate
//console.log(data);
if (!doSync)
{
card.css('left',data.position.left);
card.css('top',data.position.top);
}
else
{
//note that in this case, data.oldposition isn't accurate since
//many moves have happened since the last sync
//but that's okay becuase oldPosition isn't used right now
moveCard(card, data.position);
sendAction('moveCard', data);
}
}
});
2011-06-14 07:42:04 +08:00
}
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
2011-03-10 08:20:27 -05:00
$(function() {
2011-05-29 15:36:30 -04:00
if (boardInitialized == false)
2011-05-29 17:43:40 -04:00
blockUI('<img src="/images/ajax-loader.gif" width=43 height=11/>');
2011-05-29 15:36:30 -04:00
//setTimeout($.unblockUI, 2000);
2011-03-10 08:20:27 -05:00
$( "#create-card" )
.click(function() {
var rotation = Math.random() * 10 - 5; //add a bit of random rotation (+/- 10deg)
uniqueID = Math.round(Math.random()*99999999); //is this big enough to assure uniqueness?
//alert(uniqueID);
createCard(
2011-03-10 08:20:27 -05:00
'card' + uniqueID,
'',
58, $('div.board-outline').height(),// hack - not a great way to get the new card coordinates, but most consistant ATM
2011-03-10 08:20:27 -05:00
rotation,
randomCardColour());
});
2011-03-10 08:20:27 -05:00
// Style changer
$("#smallify").click(function(){
2011-03-12 13:40:44 -05:00
if (currentTheme == "bigcards")
2011-03-10 08:20:27 -05:00
{
changeThemeTo('smallcards');
}
2011-03-12 13:40:44 -05:00
else if (currentTheme == "smallcards")
2011-03-10 08:20:27 -05:00
{
changeThemeTo('bigcards');
}
2011-03-12 13:40:44 -05:00
/*else if (currentTheme == "nocards")
2011-03-10 08:20:27 -05:00
{
2011-03-12 13:40:44 -05:00
currentTheme = "bigcards";
2011-03-10 08:20:27 -05:00
$("link[title=cardsize]").attr("href", "css/bigcards.css");
}*/
2011-03-12 13:40:44 -05:00
sendAction('changeTheme', currentTheme);
2011-03-10 08:20:27 -05:00
return false;
});
2011-03-10 08:20:27 -05:00
$('#icon-col').hover(
function() {
$('.col-icon').fadeIn(10);
},
function() {
$('.col-icon').fadeOut(150);
}
);
2011-03-10 08:20:27 -05:00
$('#add-col').click(
function(){
createColumn('New');
return false;
}
);
2011-03-10 08:20:27 -05:00
$('#delete-col').click(
function(){
deleteColumn();
return false;
}
);
// $('#cog-button').click( function(){
// $('#config-dropdown').fadeToggle();
2011-03-10 08:20:27 -05:00
// } );
// $('#config-dropdown').hover(
2011-03-10 08:20:27 -05:00
// function(){ /*$('#config-dropdown').fadeIn()*/ },
// function(){ $('#config-dropdown').fadeOut() }
2011-03-10 08:20:27 -05:00
// );
//
2011-03-10 08:20:27 -05:00
var user_name = getCookie('scrumscrum-username');
2011-03-10 08:20:27 -05:00
$("#yourname-input").focus(function()
{
if ($(this).val() == 'unknown')
{
2011-03-10 08:20:27 -05:00
$(this).val("");
}
2011-03-10 08:20:27 -05:00
$(this).addClass('focused');
});
2011-03-10 08:20:27 -05:00
$("#yourname-input").blur(function()
{
if ($(this).val() == "")
{
$(this).val('unknown');
2011-03-10 08:20:27 -05:00
}
$(this).removeClass('focused');
2011-03-10 08:20:27 -05:00
setName($(this).val());
});
2011-03-10 08:20:27 -05:00
$("#yourname-input").val(user_name);
$("#yourname-input").blur();
$("#yourname-li").hide();
$("#yourname-input").keypress(function(e)
{
code= (e.keyCode ? e.keyCode : e.which);
if (code == 10 || code == 13)
2011-03-10 08:20:27 -05:00
{
$(this).blur();
}
});
2011-03-10 08:20:27 -05:00
$( ".sticker" ).draggable({
2011-03-10 08:20:27 -05:00
revert: true,
zIndex: 1000
});
$( ".board-outline" ).resizable( {
2011-05-27 01:08:25 -04:00
ghost: false,
minWidth: 700,
minHeight: 400 ,
maxWidth: 3200,
maxHeight: 1800,
} );
2011-06-14 07:42:04 +08:00
//A new scope for precalculating
(function() {
var offsets;
$(".board-outline").bind("resizestart", function() {
offsets = calcCardOffset();
});
$(".board-outline").bind("resize", function(event, ui) {
adjustCard(offsets, false);
});
$(".board-outline").bind("resizestop", function(event, ui) {
boardResizeHappened(event, ui);
adjustCard(offsets, true);
});
2011-06-14 07:42:04 +08:00
})();
2011-03-10 08:20:27 -05:00
2011-10-11 09:51:31 -04:00
2011-10-11 21:55:31 -04:00
$('#marker').draggable(
{
axis: 'x',
containment: 'parent'
}
);
$('#eraser').draggable(
{
axis: 'x',
containment: 'parent'
}
);
2011-10-11 09:51:31 -04:00
2011-10-15 11:59:33 -04:00
//disable image dragging
window.ondragstart = function() { return false; }
2011-10-11 09:51:31 -04:00
2011-03-10 08:20:27 -05:00
});