Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Génération de tickets pour les scénarii Scrum
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<title>Génération de tickets pour les scénarii Scrum</title>
<!--
Copyright © 2016 Simon Leblanc <contact@leblanc-simon.eu>
This work is free. You can redistribute it and/or modify it under the
terms of the Do What The Fuck You Want To Public License, Version 2,
as published by Sam Hocevar. See http://www.wtfpl.net/ for more details.
-->
<link rel="icon" href="favicon.ico" />
<link rel="icon" type="image/png" href="favicon.png" />
<link href="https://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet">
<style type="text/css">
html, body {
margin: 0;
padding: 0;
font-family: 'Ubuntu', sans-serif;
}
header, #container {
width: 98%;
margin: 1em auto;
}
#colorpicker {
position: absolute;
left: -10000px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}
/**
* Header
*/
h1 {
text-align: center;
}
header {
display: flex;
justify-content: space-between;
}
.build {
width: 45%;
border-radius: 1rem;
background-color: #eee;
padding: 1rem;
margin: 0 calc(2.5% - 1em);
display: flex;
flex-direction: column;
}
header .title {
text-align: center;
margin-bottom: 1rem;
font-size: 1.3rem;
}
input, textarea {
display: block;
width: 95%;
margin: 0.5em auto;
padding: 0.2rem;
border: 1px solid #ccc;
}
#empty {
text-align: center;
}
textarea {
height: 10rem;
}
.submit {
text-align: center;
margin-top: auto;
}
.submit button {
padding-left: 2rem;
padding-right: 2rem;
font-weight: bold;
font-size: 1.2rem;
color: #3262F9;
border-radius: 2rem;
background: #ddd;
border: none;
cursor: pointer;
}
.submit button:focus {
outline: none;
}
.submit button::before {
/**
* https://www.iconfinder.com/icons/1086770/bullets_content_form_guide_list_menu_plan_to_do_icon
* Licence : CC BY
* Author : Vladlena Shibaeva
*/
content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAADJElEQVRoQ+2YTWjUQBTH35tsk83WoiIKglhE9KLW7qZ4sQeVCiJeeuhBS2m7qYKlFIsXvciiBylaerAilP2gFDzqQQVB8dSDqMmWUvDiB1VRUMHa1e5ms5mR7FKQYjdJTRMXk8se5u0//9+8N28mg1DjD9a4fwgA/M6g8wwkGFkr09JH4JRx1J3o2waQ4npriRqdBMlOJy9wFmt8AeQ+EYPeUibCr+381xaAaZ4C6yAhY0QZF9/ZEV5tTDRe3A/IBkPUSDzPRN5b6dgCaI4XxxCNa9mUOGcl6MZ49HShDSnsU1PhUSs9WwCxePGxmubbrMTcGm/uKexCDoayqXC/lWYAYDVDqxkPMrB81oI14LCOPC2hWG/+iOlPzYhPHPpcMdwzgAO9hRM6kqNAANCgj9RM+L7pak8/W8flfkSqAc1MNnxeadwjAIZSjzYGvHDuuwCkYUEbzU5U+nZULnYBNY5VA8hmxE6fAQBa5GK0xIwLphGOccNKhlfdKCOPMlCx2tSX32H+ziTFt26YNzU8BXDL9O86AcB/s5G1nmIbF4XiBFCAiM53T93Gb26UlCcl1NHBuDfr9VGk9KZp2gDSn91eNwQJpLG41o6Ah6vBKGl+0Pc2KvVqFymwecYAAXH9dEa4Wu5MXbktIYHfVA1ATQovfQcAYCjJ2nnTiJISRgCQ1UwJuWH0H8jA2mB4soiXrDf1LW6r7MSRD27heAbQImt7Swwum8ZDCJdepIRZNyA8AmDYJOfHjAVxaHM9kHmiX59O8wNLp1FkxvGqXSgtnvR9DVT6PWstn0YBp56lhbuVNsrq60QQq+4D4/jVdwDTQEwulM/9air80I3yCU6jf5rF4FbCYW151IUcunIQHgAsn6yaXgOHEiyUm9OTSobvcVAFfxUalfONhJGzSloo33hUe2xdr0u92hXG4QM1yT+1EnRjXJKL3RSAZlP8pJWePYAzP7eWjNAwAtxDhq5dnyw3R0JMoyU8CAhSLlI38OoGaq4AVHZHtoGg3s6Q7bYSXe04Eqoxg8xmG/k75qepHR1bGbAj5FdMAODXzC+9N8iA3xn4BYtZ20B3G0sLAAAAAElFTkSuQmCC);
height: 48px;
display: inline-block;
vertical-align: middle;
}
/**
* Cards
*/
.card {
width: calc(50% - 2px);
height: 250px;
min-height: 250px;
max-height: 250px;
float: left;
border: 1px solid #000;
position: relative;
border-top-left-radius: 1rem;
border-top-right-radius: 1rem;
page-break-inside: avoid;
}
#container .title {
position: relative;
background-color: #49962C;
padding: 0.5rem;
border-top-left-radius: 1rem;
border-top-right-radius: 1rem;
font-weight: bold;
}
.color, .delete {
position: absolute;
background: none;
border: none;
cursor: pointer;
}
.color {
right: 0.5rem;
}
.delete {
right: calc(0.5em + 16px + 0.5em);
}
.color:focus, .delete:focus {
outline: none;
}
.color::before, .delete::before {
width: 16px;
height: 16px;
}
.color::before {
/**
* https://www.iconfinder.com/icons/1055087/color_wheel_palette_swatch_icon
* Licence : GPL
* Author : Nick Roach
*/
content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACoUlEQVQ4T32T3UtUQRjGn/ecs19ubuu6ZOaau4sFXviVEFEiaERGV+FNEHYhZEURQf9Af0AXUVQqREVddOFtUIRWGlFguC4aZtIePxc/cl3X1d31nJmYWV1Wg+Zq3pl5fu/MM+9L2DN0feQY5/wqEVoAqhDbnENXFOpnzOwKBOpD+RLaCebnhwoyGetDgHfshebHnPMeTdu4XV5+clOsS0BWbHkHoFEe5hzpiQi2FpZkaPWVwho8nOMQsQFF2WwVEAnQ9fDTnczJjTS05DpWHjyTIDm8RSi9eRnYiAGuErlERN0VFTXXSLwZwHexOD45j55XfbjefgaOb18BcQNFgbXpBDzaHLToGFhDG5Ti7G04Z/UUiYS6iaiTMYa793oRT6RQW+XDpbZGGIYhMsFut2Fr8DlsqRhM2z6oTVckGMAT0vXQL4Aqf0zMovtlvxTc6jiNoP/QLi/j0Sm4wr3SNLPuAtSSIAD2UzwhA8CyuJzA+w9DcLucOH/2+D8fwTnHn9AnKJkkHJUNcBQfFIBMDrCaBibjBKcGVHm2zduDsaenobA00tYymGpBFhCJjEwQ4ch0gvBGV+QVLx414bbtVitGAp61QRABUbUGmssnbBynqalwl6g8BuDFKEOKWxBwZtAaVHcRClcGYKd1pEwrVt3NUDUVjPFHFIkM1xEpw+L02Gwcn2NFaPauYVZLYjGTlqaeKvKgbG0UXssKplkVnF6/hDOm1MpCyv/KheVV2F1OvF6cw44TblLR5i3GZnwJ+0v8Egrgsd9fe0POZma+OBhzvOVcaRKxYRoYmYsiZhrSkwMWK6p9ZXlPoo+cF54LBAKpXDMJiGEU3BdF9b9mEpk5d90R4lwz5Qu2PekEWAuAQHaPfjOGPkDtCQarw/nn/wLZnxe/RFGwIAAAAABJRU5ErkJggg==);
}
.delete::before {
/**
* https://www.iconfinder.com/icons/928426/bin_delete_empty_junk_remove_trash_icon
* Licence : CC BY
* Author : Chanut is Industries
*/
content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABIUlEQVQ4T6XTOyiHURgH4Mc9xWRmYHTJYFCUTSImJUUZyMRiEIPkltFiMighk0FMFspiZDGJYjQpYXDp6IhO/y//cpbv/pzfec/7FfjnKEi+H8UEijLcN6xh8/v5b6ACDyj7I9QzqhCOfgPlaMtzRWd4SYEQuwOlfyCvOMV7CgxjK88Eg9hLgW4cYRsNaI7XIVlXnPURvejEcQrU4hpjaMQkZlCMRczG8wXU4C4FCvGEJXxgOQHCFodUI6jMtY3h3kWMeomNBOjDEOrQkgV8FQY7OEiAVqziHqHgXyPtxPm4ldM4T4BQo0PsxuXlBAYwhx7cJEDo1FuMYz8rQVOceR1TOImVb8dKBOtxlQWURL06o6FCqn6EnyrnEvJsxJ/XPgE5azkRuxeDCAAAAABJRU5ErkJggg==);
}
.description {
padding: 0.5rem;
}
.time {
position: absolute;
bottom: 0;
left: 0;
min-height: 40px;
border-top: 1px solid #000;
width: 100%;
}
.time .estimated, .time .real {
position: relative;
float: right;
min-width: 115px;
min-height: 40px;
text-align: center;
line-height: 40px;
font-weight: bold;
padding-top: 0.6rem;
}
.time .estimated {
border-left: 1px solid #000;
border-right: 1px solid #000;
}
.time .estimated::before, .time .real::before {
position: absolute;
top: 0;
left: 0;
width: 100%;
text-align: center;
font-size: 0.6rem;
line-height: normal;
border-bottom: 1px dashed #000;
}
.time .estimated::before {
content: "Estimation";
}
.time .real::before {
content: "Réel";
}
@media print {
h1, header, .delete, .color {
display: none;
}
@page { {
size: auto; /* auto is the initial value */
margin: 0mm; /* this affects the margin in the printer settings */
}
html {
background-color: #FFFFFF;
margin: 0px; /* this affects the margin on the html before sending to printer */
}
body {
margin: 10mm 15mm 10mm 15mm; /* margin you want for the content */
}
}
</style>
</head>
<body>
<h1>Génération de tickets pour les scénarii Scrum</h1>
<header>
<div class="build">
<div class="title">Générer des tickets vierges</div>
<div class="form">
<input type="number" id="empty" min="1" value="8" />
<input type="color" id="empty-color" value="#49962C">
</div>
<div class="submit">
<button id="generate-empty">Générer</button>
</div>
</div>
<div class="build">
<div class="title">Générer des tickets</div>
<div class="form">
<input type="text" id="title" placeholder="Titre des tickets" />
<textarea id="contents" placeholder="Une ligne par ticket"></textarea>
<input type="color" id="content-color" value="#49962C">
</div>
<div class="submit">
<button id="generate-content">Générer</button>
</div>
</header>
<div id="container"></div>
<input type="color" id="colorpicker">
<script>
/*******************************************************************************
*
* EXTERNAL FUNCTIONS
*
*******************************************************************************/
/**
* Escape / Unescape HTML
* @see http://jsfiddle.net/Daniel_Hug/qPUEX/show/light/
*/
(function() {
var escapeEl = document.createElement('textarea');
window.escapeHTML = function(html) {
escapeEl.textContent = html;
return escapeEl.innerHTML;
};
window.unescapeHTML = function(html) {
escapeEl.innerHTML = html;
return escapeEl.textContent;
};
})();
/**
* Convert RGB to Hex
* @see http://jsfiddle.net/Mottie/xcqpF/1/light/
*/
function rgb2hex(rgb){
rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
return (rgb && rgb.length === 4) ? "#" +
("0" + parseInt(rgb[1],10).toString(16)).slice(-2) +
("0" + parseInt(rgb[2],10).toString(16)).slice(-2) +
("0" + parseInt(rgb[3],10).toString(16)).slice(-2) : '';
}
/*******************************************************************************
*
* BASE FUNCTIONS
*
*******************************************************************************/
function addDiv(css, content, content_editable)
{
var div = document.createElement('div');
if (css) {
div.setAttribute('class', css);
}
if (content) {
div.innerHTML = content;
}
if (content_editable) {
div.setAttribute('contenteditable', 'true');
}
return div;
}
function addButton(css)
{
var button = document.createElement('button');
if (css) {
button.setAttribute('class', css);
}
return button;
}
function generateCard(title, description, color)
{
var div_card = addDiv('card');
var div_title = addDiv('title', title, 'true');
var button_delete = addButton('delete');
var button_color = addButton('color');
var div_description = addDiv('description', description, 'true');
var div_time = addDiv('time');
var div_time_real = addDiv('real', '&nbsp;');
var div_time_estimated = addDiv('estimated', '&nbsp;', 'true');
button_color.addEventListener('click', colorCard, false);
button_delete.addEventListener('click', deleteCard, false);
div_title.appendChild(button_color);
div_title.appendChild(button_delete);
if (color) {
div_title.setAttribute('style', 'background-color:' + color);
}
div_time.appendChild(div_time_real);
div_time.appendChild(div_time_estimated);
div_card.appendChild(div_title);
div_card.appendChild(div_description);
div_card.appendChild(div_time);
return div_card;
}
function deleteCard(event)
{
event.target.parentNode.parentNode.remove();
}
function colorCard(event)
{
var title = event.target.parentNode;
current_card_title = title;
colorpicker.focus();
colorpicker.value = rgb2hex(window.getComputedStyle(title, null).getPropertyValue("background-color"));
colorpicker.click();
}
/*******************************************************************************
*
* MAIN PROGRAM
*
*******************************************************************************/
var container = document.getElementById('container');
var colorpicker = document.getElementById('colorpicker');
var current_card_title = null;
document.getElementById('generate-empty').addEventListener('click', function() {
var number = parseInt(document.getElementById('empty').value, 10);
var color = document.getElementById('empty-color').value;
for (var iterator = 0; iterator < number; iterator++) {
container.appendChild(generateCard('&nbsp;', '&nbsp;', color));
}
}, false);
document.getElementById('generate-content').addEventListener('click', function() {
var title = document.getElementById('title').value;
var color = document.getElementById('content-color').value;
var contents = document.getElementById('contents').value.split('\n');
contents.forEach(function (content) {
if (!content) {
return;
}
container.appendChild(generateCard(escapeHTML(title), escapeHTML(content), color));
});
}, false);
colorpicker.addEventListener('change', function () {
if (current_card_title === null) {
return;
}
current_card_title.style.backgroundColor = this.value;
current_card_title = null;
}, false);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.