diff --git a/bookmarklet.js b/bookmarklet.js index 72a3cc7..49c1cc5 100644 --- a/bookmarklet.js +++ b/bookmarklet.js @@ -1,1560 +1,1628 @@ (function() { - var version = "4.0.6"; - console.log("Version: " + version); + var version = "4.0.6"; + console.log("Version: " + version); - var global = {}; - global.isDev = /.*jira.atlassian.com\/secure\/RapidBoard.jspa\?.*projectKey=ANERDS.*/g.test(document.URL) // Jira - || /.*pivotaltracker.com\/n\/projects\/510733.*/g.test(document.URL) // PivotTracker - || ( /.*trello.com\/.*/g.test(document.URL) && jQuery("span.js-member-name").text() =='Bengt Brodersen'); // Trello - global.isProd = !global.isDev; + var global = {}; + global.isDev = /.*jira.atlassian.com\/secure\/RapidBoard.jspa\?.*projectKey=ANERDS.*/g.test(document.URL) // Jira + || /.*pivotaltracker.com\/n\/projects\/510733.*/g.test(document.URL) // PivotTracker + || (/.*trello.com\/.*/g.test(document.URL) && jQuery("span.js-member-name").text() == 'Bengt Brodersen'); // Trello + global.isProd = !global.isDev; - window.addEventListener("error", function(event) { - var error = event.error; - console.log("ERROR: " + error.stack); - if (global.isProd) { - ga('send', 'exception', { - 'exDescription': error.message, - 'exFatal': true - }); - } + window.addEventListener("error", function(event) { + var error = event.error; + console.log("ERROR: " + error.stack); + if (global.isProd) { + ga('send', 'exception', { + 'exDescription': error.message, + 'exFatal': true + }); + } + }); + + // load jQuery + if (window.jQuery === undefined) { + appendScript('//ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js'); + } + + // wait untill all scripts loaded + appendScript('https://qoomon.github.io/void', function() { + main(); + }); + + function main() { + init(); + + // determine application + if (jQuery("meta[name='application-name'][ content='JIRA']").length > 0) { + console.log("App: " + "Jira"); + global.appFunctions = jiraFunctions; + } else if (/.*pivotaltracker.com\/.*/g.test(document.URL)) { + console.log("App: " + "PivotalTracker"); + global.appFunctions = pivotalTrackerFunctions; + } else if (/.*trello.com\/.*/g.test(document.URL)) { + console.log("App: " + "Trello"); + global.appFunctions = trelloFunctions; + } else if (/.*\/youtrack\/.*/g.test(document.URL)) { + console.log("App: " + "YouTrack"); + global.appFunctions = youTrackFunctions; + } else { + alert("Unsupported app.Please create an issue at https://github.com/qoomon/Jira-Issue-Card-Printer"); + return; + } + + //preconditions + if (jQuery("#card-print-overlay").length > 0) { + alert("Print Card already opened!"); + return; + } + + // collect selcted issues + var issueKeyList = global.appFunctions.getSelectedIssueKeyList(); + if (issueKeyList.length <= 0) { + alert("Please select at least one issue."); + return; + } + + // open print preview + jQuery("body").append(printOverlayHTML()); + jQuery("#card-print-overlay").prepend(printOverlayStyle()); + + var printFrame = jQuery("#card-print-dialog-content-iframe"); + var printWindow = printFrame[0].contentWindow; + printWindow.addEventListener("resize", function() { + redrawCards(); + }); + printWindow.matchMedia("print").addListener(function() { + redrawCards(); }); - // load jQuery - if (window.jQuery === undefined) { - appendScript('//ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js'); - } + jQuery("#rowCount").val(readCookie("card_printer_row_count", 2)); + jQuery("#columnCount").val(readCookie("card_printer_column_count", 1)); + //jQuery("#font-scale-range").val(readCookie("card_printer_font_scale",1)); + jQuery("#single-card-page-checkbox").attr('checked', readCookie("card_printer_single_card_page", 'true') == 'true'); + jQuery("#hide-description-checkbox").attr('checked', readCookie("card_printer_hide_description", 'false') == 'true'); + jQuery("#hide-assignee-checkbox").attr('checked', readCookie("card_printer_hide_assignee", 'true') == 'true'); + jQuery("#hide-due-date-checkbox").attr('checked', readCookie("card_printer_hide_due_date", 'false') == 'true'); + jQuery("#hide-status-checkbox").attr('checked', readCookie("card_printer_hide_status", 'true') == 'true'); - // wait untill all scripts loaded - appendScript('https://qoomon.github.io/void', function() { - main(); + jQuery("#card-print-dialog-title").text("Card Print - Loading " + issueKeyList.length + " issues..."); + renderCards(issueKeyList, function() { + jQuery("#card-print-dialog-title").text("Card Print"); + //print(); }); - function main() { - init(); + if (global.isProd) { + ga('send', 'pageview'); + } + } - // determine application - if (jQuery("meta[name='application-name'][ content='JIRA']").length > 0) { - console.log("App: " + "Jira"); - global.appFunctions = jiraFunctions; - } else if (/.*pivotaltracker.com\/.*/g.test(document.URL)) { - console.log("App: " + "PivotalTracker"); - global.appFunctions = pivotalTrackerFunctions; - } else if (/.*trello.com\/.*/g.test(document.URL)) { - console.log("App: " + "Trello"); - global.appFunctions = trelloFunctions; - } else if (/.*\/youtrack\/.*/g.test(document.URL)) { - console.log("App: " + "YouTrack"); - global.appFunctions = youTrackFunctions; - } else { - alert("Unsupported app.Please create an issue at https://github.com/qoomon/Jira-Issue-Card-Printer"); - return; - } + function init() { + addStringFunctions(); + addDateFunctions(); - //preconditions - if (jQuery("#card-print-overlay").length > 0) { - alert("Print Card already opened!"); - return; - } + global.hostOrigin = "https://qoomon.github.io/Jira-Issue-Card-Printer/"; + if (global.isDev) { + console.log("DEVELOPMENT"); + global.hostOrigin = "https://rawgit.com/qoomon/Jira-Issue-Card-Printer/develop/"; + } + global.resourceOrigin = global.hostOrigin + "resources/"; - // collect selcted issues - var issueKeyList = global.appFunctions.getSelectedIssueKeyList(); - if (issueKeyList.length <= 0) { - alert("Please select at least one issue."); - return; - } + if (global.isProd) { + initGoogleAnalytics(); + } + } - // open print preview - jQuery("body").append(printOverlayHTML()); - jQuery("#card-print-overlay").prepend(printOverlayStyle()); + function print() { + var printFrame = jQuery("#card-print-dialog-content-iframe"); + var printWindow = printFrame[0].contentWindow; + var printDocument = printWindow.document; - var printFrame = jQuery("#card-print-dialog-content-iframe"); - var printWindow = printFrame[0].contentWindow; - printWindow.addEventListener("resize", function(){redrawCards();}); - printWindow.matchMedia("print").addListener(function(){redrawCards();}); + if (global.isProd) { + ga('send', 'event', 'button', 'click', 'print', jQuery(".card", printDocument).length); + } - jQuery("#rowCount").val(readCookie("card_printer_row_count",2)); - jQuery("#columnCount").val(readCookie("card_printer_column_count",1)); - //jQuery("#font-scale-range").val(readCookie("card_printer_font_scale",1)); - jQuery("#single-card-page-checkbox").attr('checked',readCookie("card_printer_single_card_page", 'true' ) == 'true'); - jQuery("#hide-description-checkbox").attr('checked',readCookie("card_printer_hide_description", 'false') == 'true'); + printWindow.print(); + } - jQuery("#card-print-dialog-title").text("Card Print - Loading " + issueKeyList.length + " issues..."); - renderCards(issueKeyList, function() { - jQuery("#card-print-dialog-title").text("Card Print"); - //print(); - }); + function renderCards(issueKeyList, callback) { + var printFrame = jQuery("#card-print-dialog-content-iframe"); + var printWindow = printFrame[0].contentWindow; + var printDocument = printWindow.document; + + printDocument.open(); + printDocument.write("
"); + + jQuery("head", printDocument).append(cardCss()); + jQuery("body", printDocument).append(""); + jQuery("#preload", printDocument).append(""); + + console.log("load " + issueKeyList.length + " issues..."); + + var deferredList = []; + jQuery.each(issueKeyList, function(index, issueKey) { + var page = cardHtml(issueKey); + page.attr("index", index); + page.hide(); + page.find('.issue-id').text(issueKey); + jQuery("body", printDocument).append(page); + var deferred = addDeferred(deferredList); + global.appFunctions.getCardData(issueKey, function(cardData) { + //console.log("cardData: " + cardData); if (global.isProd) { - ga('send', 'pageview'); + ga('send', 'event', 'card', 'generate', cardData.type); } + fillCard(page, cardData); + page.show(); + redrawCards(); + deferred.resolve(); + }); + }); + console.log("wait for issues loaded..."); + + applyDeferred(deferredList, function() { + console.log("...all issues loaded."); + jQuery(printWindow).load(function() { + console.log("...all resources loaded."); + callback(); + }) + printDocument.close(); + console.log("wait for resources loaded..."); + }); + } + + function redrawCards() { + + styleCards(); + + scaleCards(); + + cropCards(); + + resizeIframe(jQuery("#card-print-dialog-content-iframe")); + } + + + function fillCard(card, data) { + //Key + card.find('.issue-id').text(data.key); + + //Type + card.find(".issue-icon").attr("type", data.type); + + //Summary + card.find('.issue-summary').text(data.summary); + + //Description + if (data.description) { + card.find('.issue-description').html(data.description); + } else { + card.find(".issue-description").addClass("hidden"); } - function init() { - addStringFunctions(); - addDateFunctions(); - - global.hostOrigin = "https://qoomon.github.io/Jira-Issue-Card-Printer/"; - if (global.isDev) { - console.log("DEVELOPMENT"); - global.hostOrigin = "https://rawgit.com/qoomon/Jira-Issue-Card-Printer/develop/"; - } - global.resourceOrigin = global.hostOrigin + "resources/"; - - if (global.isProd){ - initGoogleAnalytics(); - } + //Assignee + if (data.assignee) { + if (data.avatarUrl) { + card.find(".issue-assignee").css("background-image", "url('" + data.avatarUrl + "')"); + } else { + card.find(".issue-assignee").text(data.assignee[0].toUpperCase()); + } + } else { + card.find(".issue-assignee").addClass("hidden"); } - function print() { - var printFrame = jQuery("#card-print-dialog-content-iframe"); - var printWindow = printFrame[0].contentWindow; - var printDocument = printWindow.document; - - if (global.isProd) { - ga('send', 'event', 'button', 'click', 'print', jQuery(".card", printDocument).length); - } - - printWindow.print(); + //Due-Date + if (data.dueDate) { + card.find(".issue-due-date").text(data.dueDate); + } else { + card.find(".issue-due-box").addClass("hidden"); } - function renderCards(issueKeyList, callback) { - - var printFrame = jQuery("#card-print-dialog-content-iframe"); - var printWindow = printFrame[0].contentWindow; - var printDocument = printWindow.document; - - printDocument.open(); - printDocument.write(""); - - jQuery("head", printDocument).append(cardCss()); - jQuery("body", printDocument).append(""); - jQuery("#preload", printDocument).append(""); - - console.log("load " + issueKeyList.length + " issues..."); - - var deferredList = []; - jQuery.each(issueKeyList, function(index, issueKey) { - var page = cardHtml(issueKey); - page.attr("index", index); - page.hide(); - page.find('.issue-id').text(issueKey); - jQuery("body", printDocument).append(page); - var deferred = addDeferred(deferredList); - global.appFunctions.getCardData(issueKey, function(cardData) { - //console.log("cardData: " + cardData); - if (global.isProd) { - ga('send', 'event', 'card', 'generate', cardData.type); - } - fillCard(page, cardData); - page.show(); - redrawCards(); - deferred.resolve(); - }); - }); - console.log("wait for issues loaded..."); - - applyDeferred(deferredList, function() { - console.log("...all issues loaded."); - jQuery(printWindow).load(function() { - console.log("...all resources loaded."); - callback(); - }) - printDocument.close(); - console.log("wait for resources loaded..."); - }); + //Attachment + if (data.hasAttachment) {} else { + card.find('.issue-attachment').addClass('hidden'); } - function redrawCards() { - - var printFrame = jQuery("#card-print-dialog-content-iframe"); - var printWindow = printFrame[0].contentWindow; - var printDocument = printWindow.document; - - // hide/show description - jQuery("#styleHideDescription", printDocument).remove(); - if(jQuery("#hide-description-checkbox")[0].checked){ - var style= document.createElement('style'); - style.id = 'styleHideDescription'; - style.type ='text/css'; - style.innerHTML = ".issue-description { display: none; }" - jQuery("head", printDocument).append(style); - } - - // enable/disable single card page - jQuery("#styleSingleCardPage", printDocument).remove(); - if(jQuery("#single-card-page-checkbox")[0].checked){ - var style= document.createElement('style'); - style.id = 'styleSingleCardPage'; - style.type ='text/css'; - style.innerHTML = ".card { page-break-after: always; float: none; }" - jQuery("head", printDocument).append(style); - } - - scaleCards(); - - cropCards(); - - var printFrame = jQuery("#card-print-dialog-content-iframe"); - resizeIframe(printFrame); + //Story Points + if (data.storyPoints) { + card.find(".issue-estimate").text(data.storyPoints); + } else { + card.find(".issue-estimate").addClass("hidden"); } - - function fillCard(card, data) { - //Key - card.find('.issue-id').text(data.key); - - //Type - card.find(".issue-icon").attr("type", data.type); - - //Summary - card.find('.issue-summary').text(data.summary); - - //Description - if (data.description) { - card.find('.issue-description').html(data.description); - } else { - card.find(".issue-description").addClass("hidden"); - } - - //Assignee - if (data.assignee) { - if (data.avatarUrl) { - card.find(".issue-assignee").css("background-image", "url('" + data.avatarUrl + "')"); - } else { - card.find(".issue-assignee").text(data.assignee[0].toUpperCase()); - } - } else { - card.find(".issue-assignee").addClass("hidden"); - } - - //Due-Date - if (data.dueDate) { - card.find(".issue-due-date").text(data.dueDate); - } else { - card.find(".issue-due-box").addClass("hidden"); - } - - //Attachment - if (data.hasAttachment) {} else { - card.find('.issue-attachment').addClass('hidden'); - } - - //Story Points - if (data.storyPoints) { - card.find(".issue-estimate").text(data.storyPoints); - } else { - card.find(".issue-estimate").addClass("hidden"); - } - - //Epic - if (data.epicKey) { - card.find(".issue-epic-id").text(data.epicKey); - card.find(".issue-epic-name").text(data.epicName); - } else { - card.find(".issue-epic-box").addClass("hidden"); - } - - //QR-Code - var qrCodeUrl = 'https://chart.googleapis.com/chart?cht=qr&chs=256x256&chld=L|1&chl=' + encodeURIComponent(data.url); - card.find(".issue-qr-code").css("background-image", "url('" + qrCodeUrl + "')"); + //Epic + if (data.epicKey) { + card.find(".issue-epic-id").text(data.epicKey); + card.find(".issue-epic-name").text(data.epicName); + } else { + card.find(".issue-epic-box").addClass("hidden"); } - function scaleCards(){ - var printFrame = jQuery("#card-print-dialog-content-iframe"); + //QR-Code + var qrCodeUrl = 'https://chart.googleapis.com/chart?cht=qr&chs=256x256&chld=L|1&chl=' + encodeURIComponent(data.url); + card.find(".issue-qr-code").css("background-image", "url('" + qrCodeUrl + "')"); + } + + function styleCards() { + var printFrame = jQuery("#card-print-dialog-content-iframe"); + var printWindow = printFrame[0].contentWindow; + var printDocument = printWindow.document; + + // hide/show description + jQuery("#styleHideDescription", printDocument).remove(); + if (jQuery("#hide-description-checkbox")[0].checked) { + var style = document.createElement('style'); + style.id = 'styleHideDescription'; + style.type = 'text/css'; + style.innerHTML = ".issue-description { display: none; }" + jQuery("head", printDocument).append(style); + } + + // hide/show assignee + jQuery("#styleHideAssignee", printDocument).remove(); + if (jQuery("#hide-assignee-checkbox")[0].checked) { + var style = document.createElement('style'); + style.id = 'styleHideAssignee'; + style.type = 'text/css'; + style.innerHTML = ".issue-assignee { display: none; }" + jQuery("head", printDocument).append(style); + } + + // hide/show assignee + jQuery("#styleHideDueDate", printDocument).remove(); + if (jQuery("#hide-due-date-checkbox")[0].checked) { + var style = document.createElement('style'); + style.id = 'styleHideDueDate'; + style.type = 'text/css'; + style.innerHTML = ".issue-due-box { display: none; }" + jQuery("head", printDocument).append(style); + } + + // hide/show status + jQuery("#styleHideStatus", printDocument).remove(); + if (!jQuery("#hide-status-checkbox")[0].checked) { + var style = document.createElement('style'); + style.id = 'styleHideStatus'; + style.type = 'text/css'; + style.innerHTML = ".issue-status { display: none; }" + jQuery("head", printDocument).append(style); + } + + // enable/disable single card page + jQuery("#styleSingleCardPage", printDocument).remove(); + if (jQuery("#single-card-page-checkbox")[0].checked) { + var style = document.createElement('style'); + style.id = 'styleSingleCardPage'; + style.type = 'text/css'; + style.innerHTML = ".card { page-break-after: always; float: none; }" + jQuery("head", printDocument).append(style); + } + } + + function scaleCards() { + var printFrame = jQuery("#card-print-dialog-content-iframe"); + var printWindow = printFrame[0].contentWindow; + var printDocument = printWindow.document; + + var columnCount = jQuery("#columnCount").val(); + var rowCount = jQuery("#rowCount").val(); + + var cardCount = jQuery(".card", printDocument).length; + var pageCount = Math.ceil(cardCount / (columnCount * rowCount)) + + // size + + // size horizontal + jQuery("#styleColumnCount", printDocument).remove(); + var style = document.createElement('style'); + style.id = 'styleColumnCount'; + style.type = 'text/css'; + style.innerHTML = ".card { width: calc( 100% / " + columnCount + " - 0.0001px ); }" + jQuery("head", printDocument).append(style); + + // size horizontal + jQuery("#styleRowCount", printDocument).remove(); + var style = document.createElement('style'); + style.id = 'styleRowCount'; + style.type = 'text/css'; + style.innerHTML = ".card { height: calc( 100% / " + rowCount + " - 0.0001px ); }" + jQuery("head", printDocument).append(style); + + // scale + + jQuery("html", printDocument).css("font-size", "1cm"); + + // scale horizontal + // substract one pixel due to rounding problems + var cardMaxWidth = Math.floor(jQuery(".card", printDocument).outerWidth() / columnCount); + var cardMinWidth = jQuery(".card", printDocument).css("min-width").replace("px", ""); + var scaleWidth = cardMaxWidth / cardMinWidth; + + // scale vertical + // substract one pixel due to rounding problems + // dont know why to multiply outer height with 2 + var cardMaxHeight = Math.floor(jQuery(".card", printDocument).outerHeight() * 2 / rowCount); + var cardMinHeight = jQuery(".card", printDocument).css("min-height").replace("px", ""); + var scaleHeight = cardMaxHeight / cardMinHeight; + + // scale min + var scale = Math.min(scaleWidth, scaleHeight, 1); + if (scale < 1) { + jQuery("html", printDocument).css("font-size", scale + "cm"); + } + } + + function cropCards() { + var printFrame = jQuery("#card-print-dialog-content-iframe"); + var printWindow = printFrame[0].contentWindow; + var printDocument = printWindow.document; + + var cardElements = printDocument.querySelectorAll(".card"); + forEach(cardElements, function(cardElement) { + var cardContent = cardElement.querySelectorAll(".card-body")[0]; + if (cardContent.scrollHeight > cardContent.offsetHeight) { + cardContent.classList.add("zigzag"); + } else { + cardContent.classList.remove("zigzag"); + } + }); + } + + function forEach(array, callback) { + for (i = 0; i < array.length; i++) { + callback(array[i]); + } + } + + function closePrintPreview() { + jQuery("#card-print-overlay").remove(); + jQuery("#card-print-overlay-style").remove(); + } + + //############################################################################################################################ + //############################################################################################################################ + //############################################################################################################################ + + // http://www.cssdesk.com/T9hXg + + function printOverlayHTML() { + var result = jQuery(document.createElement('div')) + .attr("id", "card-print-overlay") + .html(multilineString(function() { +/*! +