Created pdf doesn't make line breaks using jsPDF() [duplicate] - javascript

what I'm doing is using jsPDF to create a PDF of the graph I generated. However, I am not sure how to wrap the title (added by using the text() function). The length of the title will vary from graph to graph. Currently, my titles are running off the page. Any help would be appreciated!
This is the code i have so far:
var doc = new jsPDF();
doc.setFontSize(18);
doc.text(15, 15, reportTitle);
doc.addImage(outputURL, 'JPEG', 15, 40, 180, 100);
doc.save(reportTitle);
Nothing to keep the reportTitle from running off the page

Okay I've solved this. I used the jsPDF function, splitTextToSize(text, maxlen, options). This function returns an array of strings. Fortunately, the jsPDF text() function, which is used to write to the document, accepts both strings and arrays of strings.
var splitTitle = doc.splitTextToSize(reportTitle, 180);
doc.text(15, 20, splitTitle);

You can just use the optional argument maxWidth from the text function.
doc.text(15, 15, reportTitle, { maxWidth: 40 });
That will split the text once it reaches the maxWidth and start on the next line.

Auto-paging and text wrap issue in JSPDF can achieve with following code
var splitTitle = doc.splitTextToSize($('#textarea').val(), 270);
var pageHeight = doc.internal.pageSize.height;
doc.setFontType("normal");
doc.setFontSize("11");
var y = 7;
for (var i = 0; i < splitTitle.length; i++) {
if (y > 280) {
y = 10;
doc.addPage();
}
doc.text(15, y, splitTitle[i]);
y = y + 7;
}
doc.save('my.pdf');

To wrap long string of text to page use this code:
var line = 25 // Line height to start text at
var lineHeight = 5
var leftMargin = 20
var wrapWidth = 180
var longString = 'Long text string goes here'
var splitText = doc.splitTextToSize(longString, wrapWidth)
for (var i = 0, length = splitText.length; i < length; i++) {
// loop thru each line and increase
doc.text(splitText[i], leftMargin, line)
line = lineHeight + line
}

If you need to dynamically add new lines you want to access the array returned by doc.splitTextToSize and then add more vertical space as you go through each line:
var y = 0, lengthOfPage = 500, text = [a bunch of text elements];
//looping thru each text item
for(var i = 0, textlength = text.length ; i < textlength ; i++) {
var splitTitle = doc.splitTextToSize(text[i], lengthOfPage);
//loop thru each line and output while increasing the vertical space
for(var c = 0, stlength = splitTitle.length ; c < stlength ; c++){
doc.text(y, 20, splitTitle[c]);
y = y + 10;
}
}

Working Helper function
Here's a complete helper function based on the answers by #KB1788 and #user3749946:
It includes line wrap, page wrap, and some styling control:
(Gist available here)
function addWrappedText({text, textWidth, doc, fontSize = 10, fontType = 'normal', lineSpacing = 7, xPosition = 10, initialYPosition = 10, pageWrapInitialYPosition = 10}) {
var textLines = doc.splitTextToSize(text, textWidth); // Split the text into lines
var pageHeight = doc.internal.pageSize.height; // Get page height, well use this for auto-paging
doc.setFontType(fontType);
doc.setFontSize(fontSize);
var cursorY = initialYPosition;
textLines.forEach(lineText => {
if (cursorY > pageHeight) { // Auto-paging
doc.addPage();
cursorY = pageWrapInitialYPosition;
}
doc.text(xPosition, cursorY, lineText);
cursorY += lineSpacing;
})
}
Usage
// All values are jsPDF global units (default unit type is `px`)
const doc = new jsPDF();
addWrappedText({
text: "'Twas brillig, and the slithy toves...", // Put a really long string here
textWidth: 220,
doc,
// Optional
fontSize: '12',
fontType: 'normal',
lineSpacing: 7, // Space between lines
xPosition: 10, // Text offset from left of document
initialYPosition: 30, // Initial offset from top of document; set based on prior objects in document
pageWrapInitialYPosition: 10 // Initial offset from top of document when page-wrapping
});

When we use linebreak in jsPDF we get an error stating b.match is not defined, to solve this error just unminify the js and replace b.match with String(b).match and u will get this error twice just replace both and then we get c.split is not defined just do the same in this case replace it with String(c).match and we are done. Now you can see line breaks in you pdf. Thank you

Related

How to give values from array as style to the div

I have bunch of numbers in an array and also I have the same amount div.Now I need to first value from array to gave first div and so on.
var xList = [265, 152, 364]
var yList = [125, 452, 215]
And every div have the same class name
function creatContent(e) {
var divMark = document.createElement("div");
divMark.classList = `markers mark`;
var img = $('<img class="comment" src="indeksiraj-1.png" alt="myimage" />');
$(divMark).append(img);
}
How to first value gave to first div second to the second div and so on.
And I was thinking about using css like this.
$(".markers").css({ top: yList + "px", left: xList + "px" });
Firstly, it appears you are mixing raw JS with JQuery. It is recommended that you avoid JQuery these days as the raw JS methods are just as simple, but significantly quicker, and they have been usable for the last 4 years - that is to say in all the browsers still supported by their manufacturers. I have therefore changed all JQuery bits from your question with raw JS bits in my answer.
Basic answer
Now, the correct way to do what you're asking is to perform that inside of your function. For example:
function createContent(xPos, yPos) {
var divMark = document.createElement('div');
divMark.classList = 'markers mark';
divMark.style.top = yPos + 'px';
divMark.style.left = xPos + 'px';
var img = document.createElement('img');
img.classList = 'comment';
img.src = 'indeksiraj-1.png';
img.alt = 'myimage';
divMark.appendChild(img);
}
Then you'll need to loop over the arrays to call the function.
for (var i = 0; i < xList.length && i < yList.length; i++) {
createContent(xList[i], yList[i]);
}
Further consideration
As a consideration, you could use a single array for the xList and yList, which would allow you to change your loop to something more readable
var posList = [
{x: 265, y: 125},
{x: 152, y: 452},
{x: 364, y: 215},
];
posList.forEach(({x, y}) => {
createContent(x, y);
});
Without changing function signature
Having now seen more context via your fiddle, I can see the createContent function is called from a button click, and does far more than you have included. I have kept my change to remove the JQuery bit from your snippet, and put in a placeholder for you to put in the rest of the functionality in the createContent function.
function createContent(e) {
var divMark = document.createElement('div');
divMark.classList = 'markers mark';
var img = document.createElement('img');
img.classList = 'comment';
img.src = 'indeksiraj-1.png';
img.alt = 'myimage';
divMark.appendChild(img);
// ...put the rest of the code in the funtion here
return divMark;
}
for (var i = 0; i < xList.length && i < yList.length; i++) {
var mark = createContent();
mark.style.top = yList[i] + 'px';
mark.style.left = xList[i] + 'px';
}

Given the X, Y, width and, height variables How do I find the start and end values of a shape in Google App Script?

So I was able to grab the width, hight, X, and y value of a frame in Figma. However, Google App Script is asking for start and the end of the the index of the shape in Google App script. how do I manipulate the values of X and Y to get the start and end of the the index I'm not even sure what the start and the end of the box is and how to find it.
How do I work with these the width and the height variables to find the start and end value of a shape in Google App Script
I am using Figma API and Google App Script
My end goal is to make Ann exporter from Figma to Google Slides
JSON File
absoluteBoundingBox: {
x: -460,
y: -333,
width: 586,
height: 586
},
Google App Script
var frameJSON.x = {};
var frameJSON.y = {};
var frameJSON.width = {};
var frameJSON.height = {};
var subRange = textRange.getRange();
Logger.log(
"Sub-range Start: " +
subRange.getStartIndex() +
"; Sub-range End: " +
subRange.getEndIndex() +
"; Sub-range Content: " +
subRange.asString()
);
When you insert a shape with SlidesApp you can getText to retrieve the TextRange object in it.
You can then manipulate this object to insert the text you want into your shape.
Here is some sample code:
function insertShapeWithText() {
//sample shape data
var x = 300;
var y = 250;
var width = 100;
var height = 3000;
var text = "Bla bla bla";
var pre = SlidesApp.getActivePresentation();
var slide = pre.getSlides()[0];
var shape = slide.insertShape(SlidesApp.ShapeType.DIAMOND, x, y, width, height);
shape.getText().setText(text);
}

Photoshop Scripting: Creating a selection, then fitting a text box inside

Using Javascript for Photoshop (ExtendScript) I am trying make a dynamic text box.
My end goal is a script that the user writes their own text into a new window pop up, then that text is positioned in the bottom 10% of the image, scaled dynamically to fit the bottom 10% of an image.
So, whatever the dimensions of the lower 10% (created by resizeCanvas argument) the text always fits within it comfortably. So when the user adds a few words it does not look too small and when they add a longer sentence it does not overspill.
Question originally asked here (with pictures) https://forums.adobe.com/message/10952562#10952562
Example Start Image:
start image
Window Pop up :
custom PopUp
Small Text Outcome:
outcome1
Long Text Outcome:
outcome 2
This is where I am currently:
#target Photoshop
app.preferences.rulerUnits = Units.PIXELS;
app.preferences.typeUnits = TypeUnits.PIXELS;
var doc = app.activeDocument;
var hgt10 = doc.height / 10;
var FillColor = new SolidColor;
FillColor.rgb.hexValue = 'ff0000';
var newHgt = doc.height + hgt10
doc.resizeCanvas(doc.width, newHgt, AnchorPosition.TOPCENTER);
var win = new Window('dialog', "Custom Text");
var grp1 = win.add('group');
grp1.alignChildren = "top";
var txt = grp1.add('edittext', [0, 0, 300, 150], "Write your message", {multiline: true, scrolling: true});
txt.active = true;
var grp2 = win.add('group');
var goBtn = grp2.add('button', undefined, "Run");
grp2.add('button', undefined, "Cancel");
var newLyr = doc.artLayers.add();
newLyr.kind = LayerKind.TEXT;
// CONTENTS
var txtLyr = newLyr.textItem
txtLyr.font = "ArialMT"
txtLyr.contents = txt.text
var uV = new UnitValue(20,'mm')
txtLyr.size = UnitValue(25,'mm')
txtLyr.color = FillColor;
txtLyr.position = [25, 2200] // x, y - Need to fix position to fit in the lower 10%
goBtn.onClick = function() {
win.close();
}
win.show();
So the areas I would like some assistance with is:
1) Getting the text to be positioned in the new area (created by the resizeCanvas argument extending by 10%)
2) Adding line breaks and automatically sizing to fit a variety of length text files into the field.
Kind Regards,
To add line breaks, replace all \ns with \rs (at least for Windows, I have a feeling that this Mac version may require something else, but I'm not sure):
txtLyr.contents = txt.text.replace(/\n/gm, '\r')
To position text you need to know the size (that'll depend on lines number) and leading.
var lines = txt.text.split('\n'); //getting the number of lines
var maxSize = hgt10 / lines.length; //calculating max size for a line (including the leading) = 10% of doc height devided by lines number
newLyr.textItem.useAutoLeading = true // making sure that text uses autoleading
var leading = newLyr.textItem.autoLeadingAmount; //autoleading value is in % of text size
maxSize = maxSize / leading * 100; // recalculating text size based on leading in pixels
txtLyr.size = maxSize;
txtLyr.position = [25, originalDocHeight + maxSize]
Result with one line and with several lines:

Animating SVG polygons

I wrote a code to drawing polygons:
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('width', '100%');
svg.setAttribute('height', window.innerHeight);
document.querySelector('#bg').appendChild(svg);
for(var x = 0; x < polygons.length; x++){
var polygon = document.createElementNS(svg.namespaceURI, 'polygon');
polygon.setAttribute('points', polygons[0 + x]);
polygon.setAttribute('fill', polygons[0 + x][1]);
svg.appendChild(polygon);
}
My full code with polygon points:
http://codepen.io/anon/pen/WrqrbB
I would like to animate this polygons similar to this animation:
http://codepen.io/zessx/pen/ZGBMXZ
How to animate my polygons?
You can
call an animation function to manipulate your coordinate values as desired,
convert them to a string, e.g. using .join(),
send the resulting string back to the polygon as its points attribute value, redrawing the shape (as you were already doing when you initially created your shapes), and
have the animation function, when it is finished, call itself again at a reasonable built-in time-delay using requestAnimationFrame.
The following snippet gives a basic idea of what can be done.
(Note that I've redefined the array polygons in my example so that it is different from what you had, but that was done for the sake of simplicity in this example.)
var svg = document.getElementsByTagName("svg")[0];
var polygons = [], numSteps = 100, stepNum = 0;
var coords = [
[40, 20, 80, 20, 80, 60, 40, 60],
[140, 20, 180, 20, 160, 50]
];
for (var x = 0; x < coords.length; x++) {
polygons[x] = document.createElementNS(svg.namespaceURI, 'polygon');
polygons[x].setAttribute('points', coords[x].join());
svg.appendChild(polygons[x]);
}
function anim() {
for (var x = 0; x < coords.length; x++) {
coords[x] = coords[x].map(function(coord) {
return coord + 4 * (Math.random() - 0.5);
});
polygons[x].setAttribute('points', coords[x].join());
stepNum += 1;
}
if (stepNum < numSteps) requestAnimationFrame(anim);
}
anim();
<svg></svg>
UPDATE The above snippet shows generally how to animate a polygon. In your case, however, there is a further issue. On your codepen demo, it is clear that you have hard-coded the point coordinates for each polygon separately. Thus, if you want to move one point, you're going to have to update coordinates in at least 2 if not more places, for every polygon that touches that point.
A better approach would be to create a separate array of all points and then define each polygon with respect to that array. (This is similar to how things are sometimes done in 3D graphics, e.g. WebGL.) The following code snippet demonstrates this approach.
var svg = document.getElementsByTagName("svg")[0];
var polyElems = [], numSteps = 100, stepNum = 0;
var pts = [[120,20], [160,20], [200,20], [240,20], [100,50], [140,50], [180,50], [220,50], [260,50], [120,80], [160,80], [200,80], [240,80]];
var polyPts = [[0,1,5], [1,2,6], [2,3,7], [0,4,5], [1,5,6], [2,6,7], [3,7,8], [4,5,9], [5,6,10], [6,7,11], [7,8,12], [5,9,10], [6,10,11], [7,11,12]];
for (var x = 0; x < polyPts.length; x++) {
polyElems[x] = document.createElementNS(svg.namespaceURI, 'polygon');
polyElems[x].setAttribute('fill', '#'+Math.floor(Math.random()*16777215).toString(16));
// random hex color routine from http://www.paulirish.com/2009/random-hex-color-code-snippets/
drawPolygon(x);
}
function anim() {
pts = pts.map(function(pt) {
return pt.map(function(coord) {
return coord + 3 * (Math.random() - 0.5); // move each point
});
});
for (var x = 0; x < polyPts.length; x++) {drawPolygon(x);}
stepNum += 1;
if (stepNum < numSteps) requestAnimationFrame(anim); // redo anim'n until all anim'n steps done
}
anim(); // start the animation
function drawPolygon(x) {
var ptNums = polyPts[x];
var currCoords = [pts[ptNums[0]], pts[ptNums[1]], pts[ptNums[2]]].join();
// creates a string of coordinates; note that [[1,2],[3,4],[5,6]].join() yields "1,2,3,4,5,6"
polyElems[x].setAttribute('points', currCoords);
svg.appendChild(polyElems[x]);
}
<svg></svg>

How to insert tspan into text-element via javascript [duplicate]

I have the following code:
var set = paper.set();
var text = paper.text(0, 0, 'bla1 bla2' ).attr({ fill: 'blue'});
set.push(text);
How can I change the color of the 'bla2' to green now?
I've already tried to split the string into two text-elements and assign the coordinates of the 'bla1'+ width of the 'bla1' to the second one. It didn't work since I coundn't find out the width of 'bla1'. The second problem with this solution is that I might want to change the font-size of 'bla1 bla2' which will automatically change the width of 'bla1' and distort the position of 'bla2'.
Thanks in advance!
You can try something like this:
HTML:
<div id="canvas"></div>​
JS:
var text = "this is some colored text";
var paper = Raphael('canvas', '100%', document.documentElement.clientHeight/2 );
var colors = ["#ffc000", "#1d1d1d", "#e81c6e", "#7c7c7c", "#00aff2"];
var letterSpace = 5;
var xPos = 10;
var yPos = 10;
textNodes = text.split(' ');
for( var i=0; i < textNodes.length; ++i) {
var textColor = colors[i];
var textNode = paper.text( xPos , yPos , textNodes[i]);
textNode.attr({
'text-anchor': 'start',
'font-size' : 12,
'fill' : textColor
});
xPos = xPos + textNode.getBBox().width + letterSpace;
}
​
Demo:
http://jsfiddle.net/aamir/zsS7L/

Categories