Greasy Fork is available in English.
Erzeugt aus einem Rezept ein PDF Dokument zum Herunterladen oder Drucken
// ==UserScript==// @name Chefkoch PDF export// @description Erzeugt aus einem Rezept ein PDF Dokument zum Herunterladen oder Drucken// @namespace cuzi// @oujs:author cuzi// @version 2// @include http://www.chefkoch.de/rezepte/*// @grant GM_xmlhttpRequest// @require https://greasyfork.org/scripts/15924-jspdf/code/jsPDF.js// ==/UserScript==function convertImgToDataURL(url, callback){GM_xmlhttpRequest({method: "GET",responseType : "blob",url: url,onload: function(response) {var reader = new FileReader();reader.onloadend = function () {var img = new Image();img.onload = function(){callback(reader.r###lt, parseInt(this.width,10), parseInt(this.height,10));};img.src = reader.r###lt;};reader.readAsDataURL(response.response);},});}function trimArray(arr) {return arr.map((e) => e.trim());}function trimMultiline(s) {return trimArray(s.split("\n")).join("\n").trim();}function splitText(doc, s, size) {size = size?size:500;var p = s.split("\n");var r = [];for(var i = 0; i < p.length; i++) {var t = p[i].trim();if(t) {r.push(t);}}s = r.join("\n").trim();return doc.splitTextToSize(s, size);}function makeColums(doc, x, y, fontSize, columnSep, rowSep, data) {/* Write text to pdf in columnsdata = [[text1, text2, text2],[text3, text4, text5],....]*/doc.setFontSize(fontSize);var columnWidth = [];for(var i = 0; i < data.length; i++) {for(var j = 0; j < data[i].length; j++) {var textWidth = doc.getStringUnitWidth(data[i][j]);if(columnWidth[j]) {columnWidth[j] = Math.max(columnWidth[j], fontSize * textWidth);} else {columnWidth.push(fontSize * textWidth);}}}var start_x = x;for(var i = 0; i < data.length; i++) {for(var j = 0; j < data[i].length; j++) {doc.text(x, y, data[i][j]);x += columnWidth[j] + columnSep;}x = start_x;y += doc.getLineHeight() + rowSep;}// Return total width and heightvar total_width = columnWidth.reduce((a, b) => a+b) + columnWidth.length * columnSep;var total_height = data.length * doc.getLineHeight() + data.length * rowSep;return [total_width, total_height];}function Layout(doc, x, y) {var lineSep = 0;var width = 595; // A4 = 495pt x 842ptvar height = 842;var start_x = x;var start_y = y;this.move = function move(toX,toY) {x = toX;y = toY;};this.pos = function pos() {return {"x" : x, "y" : y};};this.pageWidth = function pageWidth() {return width;};this.setLineSep = function setLineSep(newlineSep) {lineSep = newlineSepreturn this;};this.text = function text(fontSize, str) {doc.setFontSize(fontSize);doc.text(x, y, doc.splitTextToSize(str, width-x));x += doc.getStringUnitWidth(str) * fontSize;return this;};this.line = function line(fontSize, str) {doc.setFontSize(fontSize);x = start_x;var textHeight = doc.splitTextToSize(str, width-x).length * doc.getLineHeight();this.text(fontSize, str);y += textHeight + lineSep;return this;};this.r = function r() {x = start_x;};this.br = function br(numberOfNewLines) {if(numberOfNewLines === -1) {x = start_x;y -= doc.getLineHeight() - lineSep;} else if(numberOfNewLines > 1) {for(var i = 0; i < numberOfNewLines; i ++) {br(1);}} else if(numberOfNewLines < 0) {for(var i = 0; i < -numberOfNewLines; i ++) {br(-1);}} else {x = start_x;y += doc.getLineHeight() + lineSep;}return this;};this.columns = function columns(fontSize, columnSep, rowSep, data) {var res = makeColums(doc, x, y, fontSize, columnSep, rowSep, data);x += res[0];y += res[1] + lineSep;return this;};}function RecipePage() {if(!document.querySelector("#recipe-incredients")) {throw Error("RecipePage() needs a recipe page");}this.title = function getTitle() {return document.querySelector("h1").textContent.trim();};this.summary = function getSummary() {return document.querySelector(".summary")?document.querySelector(".summary").textContent.trim():"";};this.ingredients = function getIngredients() {var ingredients = [];var tr = document.querySelectorAll("#recipe-incredients tr");for(var i = 0; i < tr.length; i++) {var td = tr[i].getElementsByTagName("td");var c = [];for(var j = 0; j < td.length; j++) {c.push(td[j].textContent.trim());}if(c) {ingredients.push(c);}}return ingredients;};this.servings = function getServings() {return (document.querySelector("#divisor").value + ' ' + document.querySelector("#divisor").nextElementSibling.firstChild.data).trim();};this.details = function getDetails() {return trimMultiline(document.querySelector("#rezept-zubereitung").previousElementSibling.textContent.trim().replace(/(\s)\s*/g,"$1").replace(/\n/g," "));};this.instructions = function getInstructions() {return trimMultiline(document.querySelector("#rezept-zubereitung").textContent);};this.imageURL = function getImageURL() {if(document.querySelectorAll("#slideshow a")[0].href) {var imgs = Array.from(document.querySelectorAll("#slideshow a")).filter((e) => e.style.display == 'block');if(imgs.length && imgs[0] && imgs[0].href) {return imgs[0].href.toString();}}return false;};}function makePdf(cb, recipe, imageData, imgWidth, imgHeight) {// Generate PDFvar doc = new jsPDF("portrait", 'pt', 'a4');var layout = new Layout(doc, 20, 20);layout.setLineSep(5);layout.line(14,recipe.title());layout.line(11, recipe.summary());var image_y_start = layout.pos().y;layout.br();layout.line(13, "Zutaten (für "+recipe.servings()+")").r();layout.columns(12, 20, 5, recipe.ingredients());var image_x_start = layout.pos().x;var image_y_end = layout.pos().y;layout.line(13, "Zubereitung");layout.line(12, recipe.details());layout.line(12, recipe.instructions());if(imageData) {// Insert Imagevar paddingLeft = 10;var paddingRight = 10;var newImageWidth = layout.pageWidth() - image_x_start - paddingLeft - paddingRight;var newImageHeight = image_y_end - image_y_start;if(Math.min(newImageWidth, newImageHeight) > 20) { // Do not include images, if there's less than 20pt availablevar scale = Math.min(newImageWidth/imgWidth, newImageHeight/imgHeight);newImageWidth = Math.floor(scale * imgWidth);newImageHeight = Math.floor(scale * imgHeight);doc.addImage(imageData, 'JPEG', image_x_start+paddingLeft, image_y_start, newImageWidth, newImageHeight);}}// Show PDFvar datauristring = doc.output('datauristring');var div = document.createElement("div");div.style = "background:#90b262; position:absolute; top:15px; left:2px; padding:3px 5px;";document.body.appendChild(div);var head = document.createElement("div");head.style = "color:White; height:30px;";head.appendChild(document.createTextNode("PDF Dokument: "+(parseInt((datauristring.length-28)*0.75/102.4)/10)+"kB"));var a = document.createElement("a");a.style = "margin-left:10px; color:white; text-decoration:underline";a.href = datauristring;a.target = '_blank';a.appendChild(document.createTextNode("Download"));head.appendChild(a);var close = document.createElement("a");head.appendChild(close);close.innerHTML = '<button id="cboxClose" style="top: -15px;" type="button"><span>x</span></button>';close.style = "cursor:pointer;";close.addEventListener("click",function() {document.body.removeChild(div);});div.appendChild(head);var iframe = document.createElement("iframe");iframe.style = "width:400px; height:600px; ";div.appendChild(iframe);iframe.src = datauristring;cb(doc);}function downloadImageAndMakePdf(cb) {// Download the currently selected image and then create the PDF documentvar recipe = new RecipePage();if(recipe.imageURL()) {convertImgToDataURL(recipe.imageURL(), function(dataURI, width, height) {makePdf(cb, recipe, dataURI, width, height);});} else {makePdf(cb, recipe, false);}};(function () {// Show Buttonvar a = document.querySelector("#recipe-buttons a").cloneNode();a.innerHTML = "PDF";a.href = "javascript:void(0)";a.title = "PDF Dokument erzeugen";a.className = "button-green button-file-export";var click = function() {a.innerHTML = "Warten auf PDF...";window.setTimeout(function() {downloadImageAndMakePdf(function(doc) {window.setTimeout(function() {a.innerHTML = "PDF erstellt.";a.title = "Hier klicken um PDF zu öffnen. Rechtsklick zum Speichern.";a.removeEventListener("click", click);a.href = doc.output('datauristring');}, 5000);});},1);};a.addEventListener("click", click);document.querySelector("#recipe-buttons").insertBefore(a, document.querySelector("#recipe-buttons a"));})();