1163 lines
28 KiB
JavaScript
1163 lines
28 KiB
JavaScript
function toggleFullScreen() {
|
||
if (!document.fullscreenElement) {
|
||
document.documentElement.requestFullscreen()
|
||
} else {
|
||
if (document.exitFullscreen) {
|
||
document.exitFullscreen()
|
||
}
|
||
}
|
||
}
|
||
|
||
var cards = {}
|
||
var totalcolumns = 0
|
||
var columns = []
|
||
var currentTheme = "bigcards"
|
||
var boardInitialized = false
|
||
var keyTrap = null
|
||
|
||
var baseurl = location.pathname.substring(0, location.pathname.lastIndexOf("/"))
|
||
var socket = io.connect({ path: baseurl + "/socket.io" })
|
||
|
||
moment.locale(navigator.language || navigator.languages[0])
|
||
|
||
marked.setOptions({ sanitize: true })
|
||
|
||
//an action has happened, send it to the
|
||
//server
|
||
function sendAction(a, d) {
|
||
//console.log('--> ' + a);
|
||
|
||
var message = {
|
||
action: a,
|
||
data: d,
|
||
}
|
||
|
||
socket.json.send(message)
|
||
}
|
||
|
||
socket.on("connect", function () {
|
||
//console.log('successful socket.io connect');
|
||
|
||
//let the final part of the path be the room name
|
||
var room = location.pathname.substring(location.pathname.lastIndexOf("/"))
|
||
|
||
//imediately join the room which will trigger the initializations
|
||
sendAction("joinRoom", room)
|
||
})
|
||
|
||
socket.on("disconnect", function () {
|
||
blockUI("Serveur déconnecté. Veuillez rafraîchir la page pour essayer de vous reconnecter…")
|
||
//$('.blockOverlay').on('click', $.unblockUI);
|
||
})
|
||
|
||
socket.on("message", function (data) {
|
||
getMessage(data)
|
||
})
|
||
|
||
function unblockUI() {
|
||
$.unblockUI({ fadeOut: 50 })
|
||
}
|
||
|
||
function blockUI(message) {
|
||
message = message || "En attente…"
|
||
|
||
$.blockUI({
|
||
message: message,
|
||
|
||
css: {
|
||
border: "none",
|
||
padding: "15px",
|
||
backgroundColor: "#000",
|
||
"-webkit-border-radius": "10px",
|
||
"-moz-border-radius": "10px",
|
||
opacity: 0.5,
|
||
color: "#fff",
|
||
fontSize: "20px",
|
||
},
|
||
|
||
fadeOut: 0,
|
||
fadeIn: 10,
|
||
})
|
||
}
|
||
|
||
//respond to an action event
|
||
function getMessage(m) {
|
||
var message = m //JSON.parse(m);
|
||
var action = message.action
|
||
var data = message.data
|
||
|
||
//console.log('<-- ' + action);
|
||
|
||
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
|
||
|
||
case "roomDeny":
|
||
//this doesn't happen yet
|
||
break
|
||
|
||
case "moveCard":
|
||
moveCard($("#" + data.id), data.position)
|
||
break
|
||
|
||
case "initCards":
|
||
initCards(data)
|
||
break
|
||
|
||
case "createCard":
|
||
//console.log(data);
|
||
drawNewCard(data.id, data.text, data.x, data.y, data.rot, data.colour, null)
|
||
break
|
||
|
||
case "deleteCard":
|
||
$("#" + data.id).fadeOut(500, function () {
|
||
$(this).remove()
|
||
})
|
||
break
|
||
|
||
case "editCard":
|
||
$("#" + data.id)
|
||
.children(".content:first")
|
||
.attr("data-text", data.value)
|
||
$("#" + data.id)
|
||
.children(".content:first")
|
||
.html(marked(data.value))
|
||
break
|
||
|
||
case "initColumns":
|
||
initColumns(data)
|
||
break
|
||
|
||
case "updateColumns":
|
||
initColumns(data)
|
||
break
|
||
|
||
case "changeTheme":
|
||
changeThemeTo(data)
|
||
break
|
||
|
||
case "join-announce":
|
||
displayUserJoined(data.sid, data.user_name)
|
||
break
|
||
|
||
case "leave-announce":
|
||
displayUserLeft(data.sid)
|
||
break
|
||
|
||
case "initialUsers":
|
||
displayInitialUsers(data)
|
||
break
|
||
|
||
case "nameChangeAnnounce":
|
||
updateName(message.data.sid, message.data.user_name)
|
||
break
|
||
|
||
case "addSticker":
|
||
addSticker(message.data.cardId, message.data.stickerId)
|
||
break
|
||
|
||
case "setBoardSize":
|
||
resizeBoard(message.data)
|
||
break
|
||
|
||
case "export":
|
||
download(message.data.filename, message.data.text)
|
||
break
|
||
|
||
case "addRevision":
|
||
addRevision(message.data)
|
||
break
|
||
|
||
case "deleteRevision":
|
||
$("#revision-" + message.data).remove()
|
||
break
|
||
|
||
case "initRevisions":
|
||
$("#revisions-list").empty()
|
||
for (var i = 0; i < message.data.length; i++) {
|
||
addRevision(message.data[i])
|
||
}
|
||
break
|
||
|
||
default:
|
||
//unknown message
|
||
alert("action inconnue : " + JSON.stringify(message))
|
||
break
|
||
}
|
||
}
|
||
|
||
$(document).on("keyup", function (event) {
|
||
keyTrap = event.which
|
||
})
|
||
|
||
function drawNewCard(id, text, x, y, rot, colour, sticker, animationspeed, mx = 0 , my = 0) {
|
||
//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);\
|
||
">\
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" class="card-icon delete-card-icon bi bi-x-lg"><path d="M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8 2.146 2.854Z"></path></svg>\
|
||
<div id="content:' +
|
||
id +
|
||
'" class="content stickertarget droppable" data-text="">' +
|
||
marked(text) +
|
||
'</div><span class="filler"></span>\
|
||
</div>'
|
||
|
||
var card = $(h)
|
||
card.appendTo("#board")
|
||
$("#" + id)
|
||
.children(".content:first")
|
||
.attr("data-text", text)
|
||
|
||
//@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.on('click', function() {
|
||
// $(this).focus();
|
||
// } );
|
||
|
||
card.draggable({
|
||
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
|
||
}
|
||
},
|
||
handle: "div.content",
|
||
})
|
||
|
||
//After a drag:
|
||
card.on("dragstop", function (event, ui) {
|
||
if (keyTrap == 27) {
|
||
keyTrap = null
|
||
return
|
||
}
|
||
|
||
var data = {
|
||
id: this.id,
|
||
position: ui.position,
|
||
oldposition: ui.originalPosition,
|
||
}
|
||
|
||
sendAction("moveCard", data)
|
||
})
|
||
|
||
card.children(".droppable").droppable({
|
||
accept: ".sticker",
|
||
drop: function (event, ui) {
|
||
var stickerId = ui.draggable.attr("id")
|
||
var cardId = $(this).parent().attr("id")
|
||
|
||
addSticker(cardId, stickerId)
|
||
|
||
var data = {
|
||
cardId: cardId,
|
||
stickerId: stickerId,
|
||
}
|
||
sendAction("addSticker", data)
|
||
|
||
//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",
|
||
})
|
||
|
||
var speed = Math.floor(Math.random() * 1000)
|
||
if (typeof animationspeed != "undefined") speed = animationspeed
|
||
|
||
if (mx == 0 && my == 0) {
|
||
var startPosition = $("#create-card").position()
|
||
mx = startPosition.left;
|
||
my = startPosition.top;
|
||
}
|
||
card.css("top", my)
|
||
card.css("left", mx)
|
||
|
||
card.animate(
|
||
{
|
||
left: x + "px",
|
||
top: y + "px",
|
||
},
|
||
speed
|
||
)
|
||
|
||
|
||
card.children(".delete-card-icon").on("click", function () {
|
||
$("#" + id).remove()
|
||
//notify server of delete
|
||
sendAction("deleteCard", {
|
||
id: id,
|
||
})
|
||
})
|
||
|
||
card.children(".content").editable(
|
||
function (value, settings) {
|
||
$("#" + id)
|
||
.children(".content:first")
|
||
.attr("data-text", value)
|
||
onCardChange(id, value)
|
||
return marked(value)
|
||
},
|
||
{
|
||
type: "textarea",
|
||
data: function () {
|
||
return $("#" + id)
|
||
.children(".content:first")
|
||
.attr("data-text")
|
||
},
|
||
submit: "OK",
|
||
style: "inherit",
|
||
cssclass: "card-edit-form",
|
||
placeholder: "Double cliquez pour m’éditer",
|
||
onblur: "submit",
|
||
event: "dblclick", //event: 'mouseover'
|
||
}
|
||
)
|
||
|
||
//add applicable sticker
|
||
if (sticker !== null) addSticker(id, sticker)
|
||
}
|
||
|
||
function onCardChange(id, text) {
|
||
sendAction("editCard", {
|
||
id: id,
|
||
value: text,
|
||
})
|
||
}
|
||
|
||
function moveCard(card, position) {
|
||
card.animate(
|
||
{
|
||
left: position.left + "px",
|
||
top: position.top + "px",
|
||
},
|
||
500
|
||
)
|
||
}
|
||
|
||
function addSticker(cardId, stickerId) {
|
||
stickerContainer = $("#" + cardId + " .filler")
|
||
|
||
if (stickerId === "nosticker") {
|
||
stickerContainer.html("")
|
||
return
|
||
}
|
||
|
||
if (Array.isArray(stickerId)) {
|
||
for (var i in stickerId) {
|
||
stickerContainer.prepend('<img src="images/stickers/' + stickerId[i] + '.png">')
|
||
}
|
||
} else {
|
||
if (stickerContainer.html().indexOf(stickerId) < 0)
|
||
stickerContainer.prepend('<img src="images/stickers/' + stickerId + '.png">')
|
||
}
|
||
}
|
||
|
||
//----------------------------------
|
||
// cards
|
||
//----------------------------------
|
||
function createCard(id, text, x, y, rot, colour, mx = 0,my = 0) {
|
||
drawNewCard(id, text, x, y, rot, colour, null, null, mx, my)
|
||
|
||
var action = "createCard"
|
||
|
||
var data = {
|
||
id: id,
|
||
text: text,
|
||
x: x,
|
||
y: y,
|
||
rot: rot,
|
||
colour: colour,
|
||
}
|
||
|
||
sendAction(action, data)
|
||
}
|
||
|
||
function randomCardColour() {
|
||
var colours = ["yellow", "green", "blue", "white"]
|
||
|
||
var i = Math.floor(Math.random() * colours.length)
|
||
|
||
return colours[i]
|
||
}
|
||
|
||
function initCards(cardArray) {
|
||
//first delete any cards that exist
|
||
$(".card").remove()
|
||
|
||
cards = cardArray
|
||
|
||
for (var i in cardArray) {
|
||
card = cardArray[i]
|
||
|
||
drawNewCard(card.id, card.text, card.x, card.y, card.rot, card.colour, card.sticker, 0)
|
||
}
|
||
|
||
boardInitialized = true
|
||
unblockUI()
|
||
}
|
||
|
||
//----------------------------------
|
||
// cols
|
||
//----------------------------------
|
||
|
||
function drawNewColumn(columnName) {
|
||
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: "Nouveau",
|
||
onblur: "submit",
|
||
width: "",
|
||
height: "",
|
||
xindicator: '<img src="images/ajax-loader.gif">',
|
||
event: "dblclick", //event: 'mouseover'
|
||
}
|
||
)
|
||
|
||
$(".col:last").fadeIn(500)
|
||
|
||
totalcolumns++
|
||
}
|
||
|
||
function onColumnChange(id, text) {
|
||
var names = Array()
|
||
|
||
//console.log(id + " " + text );
|
||
|
||
//Get the names of all the columns right from the DOM
|
||
$(".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())
|
||
}
|
||
})
|
||
|
||
updateColumns(names)
|
||
}
|
||
|
||
function displayRemoveColumn() {
|
||
if (totalcolumns <= 0) return false
|
||
|
||
$(".col:last").fadeOut(150, function () {
|
||
$(this).remove()
|
||
})
|
||
|
||
totalcolumns--
|
||
}
|
||
|
||
function createColumn(name) {
|
||
if (totalcolumns >= 8) return false
|
||
|
||
drawNewColumn(name)
|
||
columns.push(name)
|
||
|
||
var action = "updateColumns"
|
||
|
||
var data = columns
|
||
|
||
sendAction(action, data)
|
||
}
|
||
|
||
function deleteColumn() {
|
||
if (totalcolumns <= 0) return false
|
||
|
||
displayRemoveColumn()
|
||
columns.pop()
|
||
|
||
var action = "updateColumns"
|
||
|
||
var data = columns
|
||
|
||
sendAction(action, data)
|
||
}
|
||
|
||
function updateColumns(c) {
|
||
columns = c
|
||
|
||
var action = "updateColumns"
|
||
|
||
var data = columns
|
||
|
||
sendAction(action, data)
|
||
}
|
||
|
||
function deleteColumns(next) {
|
||
//delete all existing columns:
|
||
$(".col").fadeOut("slow", next())
|
||
}
|
||
|
||
function initColumns(columnArray) {
|
||
totalcolumns = 0
|
||
columns = columnArray
|
||
|
||
$(".col").remove()
|
||
|
||
for (var i in columnArray) {
|
||
column = columnArray[i]
|
||
|
||
drawNewColumn(column)
|
||
}
|
||
}
|
||
|
||
function changeThemeTo(theme) {
|
||
currentTheme = theme
|
||
if (theme == 'bigcards') {
|
||
$("#board").removeClass('smallcards')
|
||
} else {
|
||
$("#board").removeClass('bigcards')
|
||
}
|
||
$("#board").addClass(theme)
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////
|
||
////////// 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()) + ';SameSite=Strict'
|
||
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)
|
||
}
|
||
}
|
||
}
|
||
|
||
function setName(name) {
|
||
sendAction("setUserName", name)
|
||
|
||
setCookie("scrumscrum-username", name, 365)
|
||
}
|
||
|
||
function displayInitialUsers(users) {
|
||
for (var 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)
|
||
|
||
$("#names-ul").append('<li id="user-' + sid + '">' + name + "</li>")
|
||
}
|
||
|
||
function displayUserLeft(sid) {
|
||
name = ""
|
||
if (name) name = user_name
|
||
else name = sid
|
||
|
||
var id = "#user-" + sid.toString()
|
||
|
||
$("#names-ul")
|
||
.children(id)
|
||
.fadeOut(1000, function () {
|
||
$(this).remove()
|
||
})
|
||
}
|
||
|
||
function updateName(sid, name) {
|
||
var id = "#user-" + sid.toString()
|
||
|
||
$("#names-ul").children(id).text(name)
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////
|
||
|
||
function boardResizeHappened(event, ui) {
|
||
var newsize = ui.size
|
||
|
||
sendAction("setBoardSize", newsize)
|
||
}
|
||
|
||
function resizeBoard(size) {
|
||
$(".board-outline").animate({
|
||
height: size.height,
|
||
width: size.width,
|
||
})
|
||
}
|
||
//////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////
|
||
|
||
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").length - 1) {
|
||
offsets[card.attr("id")] = {
|
||
col: col,
|
||
x: (card.offset().left - col.offset().left) / col.outerWidth(),
|
||
}
|
||
return false
|
||
}
|
||
})
|
||
})
|
||
return offsets
|
||
}
|
||
|
||
//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 () {
|
||
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)
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////
|
||
|
||
function download(filename, text) {
|
||
var element = document.createElement("a")
|
||
var mime = "text/plain"
|
||
if (filename.match(/.csv$/)) {
|
||
mime = "text/csv"
|
||
}
|
||
element.setAttribute("href", "data:" + mime + ";charset=utf-8," + encodeURIComponent(text))
|
||
element.setAttribute("download", filename)
|
||
|
||
element.style.display = "none"
|
||
document.body.appendChild(element)
|
||
element.click()
|
||
document.body.removeChild(element)
|
||
}
|
||
|
||
function addRevision(timestamp) {
|
||
var li = $('<li id="revision-' + timestamp + '"></li>')
|
||
var s1 = $("<span></span>")
|
||
var s2 = $('<img src="/images/stickers/sticker-deletestar.png" alt="delete revision">')
|
||
if (typeof timestamp === "string") {
|
||
timestamp = parseInt(timestamp)
|
||
}
|
||
s1.text(moment(timestamp).format("LLLL"))
|
||
|
||
li.append(s1)
|
||
li.append(s2)
|
||
$("#revisions-list").append(li)
|
||
|
||
// $('body').on("click", s1, function () {
|
||
// socket.json.send({
|
||
// action: "exportRevision",
|
||
// data: timestamp,
|
||
// })
|
||
// })
|
||
// $('body').on("click", s2, function () {
|
||
// socket.json.send({
|
||
// action: "deleteRevision",
|
||
// data: timestamp,
|
||
// })
|
||
// })
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////
|
||
|
||
$(function () {
|
||
//disable image dragging
|
||
//window.ondragstart = function() { return false; };
|
||
|
||
if (boardInitialized === false) blockUI('<img src="images/ajax-loader.gif" width=43 height=11/>')
|
||
|
||
//setTimeout($.unblockUI, 2000);
|
||
|
||
$(".add-post-it").on("click", function (e) {
|
||
var rotation = Math.random() * 10 - 5 //add a bit of random rotation (+/- 10deg)
|
||
var cardLeft = 150 + Math.random() * 400
|
||
var cardTop = 20 + Math.random() * 50
|
||
var uniqueID = Math.round(Math.random() * 99999999) //is this big enough to assure uniqueness?
|
||
console.log(e.clientX, e.clientY);
|
||
createCard("card" + uniqueID, "", cardLeft, cardTop, rotation, $(this).data("color"), e.clientX, e.clientY)
|
||
})
|
||
|
||
// Style changer
|
||
$("#smallify").on("click", function () {
|
||
if (currentTheme == "bigcards") {
|
||
changeThemeTo("smallcards")
|
||
} else if (currentTheme == "smallcards") {
|
||
changeThemeTo("bigcards")
|
||
}
|
||
sendAction("changeTheme", currentTheme)
|
||
|
||
return false
|
||
})
|
||
|
||
$("#icon-col").on(
|
||
"hover",
|
||
function () {
|
||
$(".col-icon").fadeIn(10)
|
||
},
|
||
function () {
|
||
$(".col-icon").fadeOut(150)
|
||
}
|
||
)
|
||
|
||
$("#add-col").on("click", function () {
|
||
createColumn("Nouvelle colonne")
|
||
return false
|
||
})
|
||
|
||
$("#delete-col").on("click", function () {
|
||
deleteColumn()
|
||
return false
|
||
})
|
||
|
||
var user_name = getCookie("scrumscrum-username")
|
||
|
||
$("#yourname-input").on("focus", function () {
|
||
if ($(this).val() == "anonyme") {
|
||
$(this).val("")
|
||
}
|
||
|
||
$(this).addClass("focused")
|
||
})
|
||
|
||
$("#yourname-input").on("blur", function () {
|
||
if ($(this).val() === "") {
|
||
$(this).val("anonyme")
|
||
}
|
||
$(this).removeClass("focused")
|
||
|
||
setName($(this).val())
|
||
})
|
||
|
||
$("#yourname-input").val(user_name)
|
||
$("#yourname-input").trigger("blur")
|
||
|
||
$("#yourname-li").hide()
|
||
|
||
$("#yourname-input").on("keypress", function (e) {
|
||
code = e.keyCode ? e.keyCode : e.which
|
||
if (code == 10 || code == 13) {
|
||
$(this).trigger("blur")
|
||
}
|
||
})
|
||
|
||
$(".sticker").draggable({
|
||
revert: true,
|
||
zIndex: 1000,
|
||
})
|
||
|
||
$(".board-outline").resizable({
|
||
ghost: false,
|
||
minWidth: 640,
|
||
minHeight: 480,
|
||
maxWidth: 1140,
|
||
maxHeight: 855,
|
||
})
|
||
|
||
//A new scope for precalculating
|
||
;(function () {
|
||
var offsets
|
||
|
||
$(".board-outline").on("resizestart", function () {
|
||
offsets = calcCardOffset()
|
||
})
|
||
$(".board-outline").on("resize", function (event, ui) {
|
||
adjustCard(offsets, false)
|
||
})
|
||
$(".board-outline").on("resizestop", function (event, ui) {
|
||
boardResizeHappened(event, ui)
|
||
adjustCard(offsets, true)
|
||
})
|
||
})()
|
||
|
||
$("#marker").draggable({
|
||
axis: "x",
|
||
containment: "parent",
|
||
})
|
||
|
||
$("#eraser").draggable({
|
||
axis: "x",
|
||
containment: "parent",
|
||
})
|
||
|
||
$("#export-txt").on("click", function () {
|
||
socket.json.send({
|
||
action: "exportTxt",
|
||
data: $(".col").length !== 0 ? $(".col").css("width").replace("px", "") : null,
|
||
})
|
||
})
|
||
|
||
$("#export-csv").on("click", function () {
|
||
socket.json.send({
|
||
action: "exportCsv",
|
||
data: $(".col").length !== 0 ? $(".col").css("width").replace("px", "") : null,
|
||
})
|
||
})
|
||
|
||
$("#export-json").on("click", function () {
|
||
socket.json.send({
|
||
action: "exportJson",
|
||
data: {
|
||
width: $(".board-outline").css("width").replace("px", ""),
|
||
height: $(".board-outline").css("height").replace("px", ""),
|
||
},
|
||
})
|
||
})
|
||
|
||
$("#import-file").on("click", function (evt) {
|
||
evt.stopPropagation()
|
||
evt.preventDefault()
|
||
|
||
var f = $("#import-input").get(0).files[0]
|
||
var fr = new FileReader()
|
||
fr.onloadend = function () {
|
||
var text = fr.result
|
||
socket.json.send({
|
||
action: "importJson",
|
||
data: JSON.parse(text),
|
||
})
|
||
}
|
||
fr.readAsText(f)
|
||
})
|
||
|
||
$("#create-revision").on("click", function () {
|
||
socket.json.send({
|
||
action: "createRevision",
|
||
data: {
|
||
width: $(".board-outline").css("width").replace("px", ""),
|
||
height: $(".board-outline").css("height").replace("px", ""),
|
||
},
|
||
})
|
||
})
|
||
})
|
||
|
||
/** Doubleclick on mobile + Layout Framemo with tabs **/
|
||
$(document).ready(function () {
|
||
if (window.location.href != window.location.protocol + "//" + window.location.host + "/") {
|
||
// Not on homepage
|
||
|
||
/** Double click on mobile interface **/
|
||
|
||
var clickTimer = null
|
||
var clickTarget = null
|
||
var editTarget = null
|
||
|
||
function doubletapCards(selector) {
|
||
$(selector + " .stickertarget").addClass("doubletap") // Escape multi bound
|
||
|
||
$(selector + " .doubletap").on("click", function () {
|
||
clickTarget = selector.replace("#", "")
|
||
|
||
if (clickTimer == null) {
|
||
clickTimer = setTimeout(function () {
|
||
clickTimer = null
|
||
}, 1000)
|
||
} else {
|
||
//console.log('doubleclick : '+clickTimer+':'+editTarget);
|
||
clearTimeout(clickTimer)
|
||
clickTimer = null
|
||
|
||
if (editTarget == clickTarget && clickTarget !== undefined && clickTarget !== null) {
|
||
$("#" + clickTarget.replace("content:", "") + " .doubletap").trigger("dblclick")
|
||
}
|
||
}
|
||
|
||
editTarget = clickTarget
|
||
})
|
||
}
|
||
|
||
function doubletapTitle(selector) {
|
||
$(selector).addClass("doubletap") // Escape multi bound
|
||
|
||
$(selector + ".doubletap").on("click", function () {
|
||
clickTarget = selector.replace("#", "")
|
||
|
||
if (clickTimer == null) {
|
||
clickTimer = setTimeout(function () {
|
||
clickTimer = null
|
||
}, 1000)
|
||
} else {
|
||
//console.log('doubleclick : '+clickTimer+':'+editTarget);
|
||
clearTimeout(clickTimer)
|
||
clickTimer = null
|
||
|
||
if (editTarget == clickTarget && clickTarget !== undefined && clickTarget !== null) {
|
||
$("#" + clickTarget + ".doubletap").trigger("dblclick")
|
||
}
|
||
}
|
||
|
||
editTarget = clickTarget
|
||
})
|
||
}
|
||
|
||
setInterval(function () {
|
||
// Add periodically the doubletap event on new cards
|
||
|
||
$(".stickertarget:not(.doubletap)").each(function () {
|
||
doubletapCards("#" + $(this).attr("id").replace("content:", ""))
|
||
})
|
||
$("#board-table .col h2:not(.doubletap)").each(function () {
|
||
doubletapTitle("#" + $(this).attr("id"))
|
||
})
|
||
}, 500)
|
||
|
||
/** Layout Framemo - Tabs **/
|
||
|
||
// Defaut board real size (not 'auto' or 'inherit') saved in database
|
||
// in order to be able to center it
|
||
var boardReady = setInterval(function () {
|
||
if (boardInitialized) {
|
||
// when board is ready
|
||
if ($(".board-outline").attr("style") === undefined) {
|
||
// check if size is imported from db
|
||
$(".board-outline").css({
|
||
width: $(".board-outline.ui-resizable").width() + 16 + "px",
|
||
height: "466px",
|
||
})
|
||
var data = {}
|
||
data.size = {
|
||
height: 466,
|
||
width: $(".board-outline.ui-resizable").width() + 16,
|
||
}
|
||
boardResizeHappened("resizestop", data) // using scrumblr function that keep size in db after a resize
|
||
}
|
||
clearInterval(boardReady)
|
||
}
|
||
}, 500)
|
||
|
||
// $("#scrumblr")
|
||
// .append($(".names, .stickers, .buttons"))
|
||
// .after(
|
||
// '<div role="tabpanel" class="tab-pane" id="export-import"></div>' +
|
||
// '<div role="tabpanel" class="tab-pane" id="share"></div>' +
|
||
// '<div role="tabpanel" class="tab-pane" id="revisions"></div>' +
|
||
// '<div role="tabpanel" class="tab-pane" id="about"></div>'
|
||
// )
|
||
|
||
// $("#export-import").append($(".export, .import"))
|
||
// $("#share").append($(".share"))
|
||
// $("#revisions").append($(".revisions"))
|
||
// $("#about").append($("#tuto-faq, #le-logiciel, #jardin"))
|
||
|
||
// Style
|
||
$("#smallify").on("click", function () {
|
||
if (currentTheme == "bigcards") {
|
||
$(this).children("i").removeClass("fa-search-plus").addClass("fa-search-minus")
|
||
} else {
|
||
$(this).children("i").removeClass("fa-search-minus").addClass("fa-search-plus")
|
||
}
|
||
})
|
||
|
||
$("#full-page").on("click", function () {
|
||
if ($(this).children("i").hasClass("fa-expand")) {
|
||
$(this).children("i").removeClass("fa-expand").addClass("fa-compress")
|
||
$("#header-bar").hide()
|
||
} else {
|
||
$(this).children("i").removeClass("fa-compress").addClass("fa-expand")
|
||
$("#header-bar").show()
|
||
}
|
||
toggleFullScreen()
|
||
})
|
||
|
||
/** Mode iframe **/
|
||
if (top.location != self.document.location) {
|
||
$("#header-bar").hide()
|
||
}
|
||
|
||
// put URL in share input
|
||
var mainurl = location.toString().split('#')[0]
|
||
$(".replace-url").val(mainurl)
|
||
$(".share-iframe").text($(".share-iframe").text().replace('{{replace-url}}', mainurl))
|
||
// copy URL to clipboard
|
||
$("#copyurl").on("click", function (e) {
|
||
e.preventDefault()
|
||
var node = document.getElementById("taburl")
|
||
node.disabled = null
|
||
node.select()
|
||
var success = document.execCommand("copy")
|
||
if (success) {
|
||
getSelection().removeAllRanges()
|
||
node.disabled = "disabled"
|
||
alert("URL du tableau copiée dans votre presse-papier !")
|
||
} else {
|
||
alert(
|
||
"Impossible de copier l'URL du tableau dans votre presse-papier. Veuillez copier son adresse manuellement (Ctrl+C)."
|
||
)
|
||
}
|
||
})
|
||
}
|
||
})
|
||
|
||
function go() {
|
||
var value = document.forms[0].elements["name"].value
|
||
value = value.replace(/[\/\?&#]/g, "")
|
||
window.location.href = value
|
||
return false
|
||
}
|
||
$(function () {
|
||
var headerBarUrl = $("#header-bar").data("url")
|
||
if (headerBarUrl) {
|
||
var getJSON = function (url, callback) {
|
||
var xhr = new XMLHttpRequest()
|
||
xhr.open("GET", url, true)
|
||
xhr.responseType = "json"
|
||
xhr.onload = function () {
|
||
var status = xhr.status
|
||
if (status === 200) {
|
||
callback(null, xhr.response)
|
||
} else {
|
||
callback(status, xhr.response)
|
||
}
|
||
}
|
||
xhr.send()
|
||
}
|
||
|
||
getJSON(headerBarUrl, function (err, data) {
|
||
if (err !== null) {
|
||
console.log("Something went wrong: " + err)
|
||
} else {
|
||
document.getElementById("header-bar").innerHTML = data.markup
|
||
var styleElement = document.createElement("style")
|
||
styleElement.innerHTML = data.style
|
||
document.getElementById("header-bar").appendChild(styleElement)
|
||
}
|
||
})
|
||
}
|
||
})
|
||
|
||
$(function () {
|
||
// check if hash used to show informations
|
||
if (window.location.hash == '#settings' || window.location.hash == '#share') {
|
||
toggleNav(window.location.hash)
|
||
}
|
||
// Toggle Nav on Click
|
||
$(".toggle-nav").on("click", function () {
|
||
var target = $(this).attr("href")
|
||
|
||
if (target === '#' || ($('#site-wrapper').hasClass('show-nav') && target == window.location.hash)) {
|
||
target = false
|
||
history.replaceState('', '', '#');
|
||
} else {
|
||
history.replaceState('', '', target);
|
||
}
|
||
toggleNav(target)
|
||
return false
|
||
})
|
||
// When nav opened, a click on the canvas hides the menu
|
||
$("body").on("click", ".show-nav #site-canvas main, .show-nav .main-header", function (e) {
|
||
history.replaceState('', '', '#');
|
||
toggleNav(false)
|
||
return false
|
||
})
|
||
$(".backgrounds .bg").on("click", function () {
|
||
if ($(this).hasClass("selected")) {
|
||
$("body").css("background-image", "none")
|
||
$(this).removeClass("selected")
|
||
} else {
|
||
$(".selected").removeClass("selected")
|
||
$('.bgurl').val('')
|
||
$("body").css("background-image", 'url("/' + $(this).attr("src") + '")')
|
||
$(this).addClass("selected")
|
||
}
|
||
})
|
||
$('.bgurl').on('change', function() {
|
||
var url = $(this).val()
|
||
if (url) {
|
||
$(".selected").removeClass("selected")
|
||
$("body").css("background-image", 'url("' + url + '")')
|
||
}
|
||
})
|
||
})
|
||
|
||
function toggleNav(target) {
|
||
if ($("#site-wrapper").hasClass("show-nav") && target === false) {
|
||
$("#site-wrapper").removeClass("show-nav")
|
||
} else {
|
||
$("#share, #settings").hide()
|
||
if (target !== false) {
|
||
$(target).show()
|
||
}
|
||
$("#site-wrapper").addClass("show-nav")
|
||
}
|
||
return false
|
||
}
|