jsPDF - fromHTML does not write at the correct page - jspdf

I am doing a small project with jsPDF.
I need to write colored text, changing the font size and using bold text. Therefore fromHtml is my choise, because i can easyly do it with css and html.
The problem is that only around the half of the page can be used to write with fromHtml. If it try to write beyond it a new page is created and the text is wirtten there.
Here a small html example with the javascript code, that can be run on it´s own.
<!DOCTYPE html>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.debug.js" integrity="sha384-NaWTHo/8YCBYJ59830LTz/P4aQZK1sS0SneOgAvhsIl3zBu8r9RevNg5lHCHAuQ/" crossorigin="anonymous"></script>
<script type="text/javascript">
function fromHtmlTest() {
var doc = new jsPDF({
orientation: 'l',
unit: 'px',
format: [30, 30]
});
// doc.setFontSize(1); // the workaround for this problem
var toWrite = ["1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th"];
for (var i = 0; i < toWrite.length; i++) {
doc.fromHTML(
'<div style="font-size:1">' + toWrite[i] + '</div>'
, 1 // x
, i // y
, {
'width': 10,
'elementHandlers': {}
}
)
}
doc.save('Test.pdf');
}
</script>
<body>
<input type="button" value="Start" onclick="fromHtmlTest()" />
</body>
Here an immage of the pdf after running the code:
fromHtml example - code result
"8th" should be directly under "7th" and not at the next page.
If "9th" would be added to the array another page would also be added.
How can i use the whole page with fromHtml?
Edit:
As workaround "doc.setFontSize(1);" does the trick. I have added it to the example code as a comment.

Related

Allow Dropzone js to upload only zip files

In my mvc net core app I need to implement drag&drop files uploader. I found Dropzone js and hoping to use it in my purposes. But can't configure it, I need to allow it upload ony zip files.
My code:
<div class="row">
<div class="col-md-9">
<div id="dropzone">
<form action="/Home/Upload" class="dropzone needsclick dz-clickable" id="uploader">
<div class="dz-message needsclick">
Drop files here or click to upload.<br>
</div>
</form>
</div>
</div>
</div>
<script>
$(document).ready(function () {
Dropzone.options.uploader = {
paramName: "file",
maxFilesize: 256,
acceptedFiles: "application/zip,application/octet-stream,application/x-zip-compressed,multipart/x-zip,.zip",
maxFiles: 1
};
});
</script>
Also of course I have controller:
[HttpPost]
public async Task<IActionResult> Upload(IFormFile file)
{
var uploads = Path.Combine(_environment.ContentRootPath, "Uploads");
if (file.Length > 0)
{
using (var fileStream = new FileStream(Path.Combine(uploads, file.FileName), FileMode.Create))
{
await file.CopyToAsync(fileStream);
}
}
return RedirectToAction("Index");
}
But still, application allows to upload any file with any MIME type. Where is a problem?
Also restriction of maxFiles isn't working too - it allows me to upload infinite count of files.
You can use option of dropzone.js name acceptedfile.
Dropzone.options.myAwesomeDropzone = {
....
acceptedFiles: ".zip",
....
};
According to the documentation (https://www.dropzonejs.com/#configuration), you can do it like this:
Dropzone.options.myAwesomeDropzone = {
accept: function(file, done) {
if (file.name.endsWith !== ".zip") {
done("Naha, you don't.");
}
else { done(); }
}
};
A function that gets a file and a done function as parameters. If the
done function is invoked without arguments, the file is "accepted" and
will be processed. If you pass an error message, the file is rejected,
and the error message will be displayed. This function will not be
called if the file is too big or doesn't match the mime types.
Edit:
Here is a fiddle to demonstrate it: http://jsfiddle.net/behyzjng/15/
Set acceptedFiles: 'application/zip' in defaultOptions
Here are the documentation for you to work on Dropzone.js:
Github: https://github.com/dropzone/dropzone
Docs: https://docs.dropzone.dev
check all avaliable options at https://github.com/dropzone/dropzone/blob/main/src/options.js
check the desired extensions allowed and write the MIME type as a value of acceptedFiles at https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
Working solution here:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://unpkg.com/dropzone#5/dist/min/dropzone.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/dropzone#5/dist/min/dropzone.min.css" type="text/css" />
<title>Document</title>
</head>
<body>
<style>
.my-dropzone {
width: 100%;
height: 100px;
border: 1px dashed;
display: flex;
align-items: center;
justify-content: center;
}
</style>
<div class="my-dropzone">
Drag and drop zip files here, or click here to upload.
</div>
<script>
// Dropzone.js
// Github: https://github.com/dropzone/dropzone
// Docs: https://docs.dropzone.dev
// check all avaliable options at
// https://github.com/dropzone/dropzone/blob/main/src/options.js
const defaultOptions = {
url: "/file/post",
// check the desired extensions allowed and write the MIME type as a value of acceptedFiles at
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
acceptedFiles: 'application/zip'
};
// Dropzone has been added as a global variable.
const dropzone = new Dropzone("div.my-dropzone", defaultOptions);
</script>
</body>
</html>

Reset Zoom on iOS after viewport width change

we are making an HTML5 app where width is not know at design time.
So we change the viewport tag at runtime to match the desidered size.
e.g.
<meta name="viewport" id="viewport-meta" content="width=' + params.mobilePortraitWidth + ', initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
The problem on iOS is that after we change the viewport size, view is not correctly scaled until we double tap the screen.
EDIT, after double tap is all fine, so: how can we "DOUBLE TAP" programmatically?
Thank you very much
NSString *js = #"var t=document.createElement('meta'); t.name="viewport"; t.content="initial-scale=1.0, maximum-scale=3.0"; document.getElementsByTagName('head')[0].appendChild(t);";
[myWebView stringByEvaluatingJavaScriptFromString:js];
EDIT
Thanks for update.
I had very similar issue and remember that setting viewport meta tag solved it.
If you are trying to modify this meta tag just after loading html, try doing that in webViewDidFinishLoad (loadRequest is asynchronous).
Another solution would be to read your html file into NSString and replace that meta tag before loading it to webView.
Hope it helps!
Thank you very much for your replies, I would like to share the solution we found after some test on iPhone 5s with iOS 9.2 and iPad Air with iOS 8.4.
Basically, to make it work, we didn't set initial-scale=1.0, maximum-scale=1.0, user-scalable=no
Following a working example
<html>
<head>
<meta name="viewport" id="viewport-meta" content="width=device-width, user-scalable=no" />
<style>
html, body { -webkit-text-size-adjust: 100%; }
h1 { padding: 1em; background-color: #FF80BB; }
</style>
</head>
<body>
<h1>I am the page content</h1>
<button id="s320">Set 320</button><br />
<button id="s640">Set 640</button><br />
<button id="s960">Set 960</button>
<script>
function setViewportWidth(newWidth) {
var m = document.getElementById("viewport-meta");
m.setAttribute('content', 'width=' + newWidth + ', user-scalable=no');
}
document.getElementById("s320").onclick = function () { return setViewportWidth(320); };
document.getElementById("s640").onclick = function () { return setViewportWidth(640); };
document.getElementById("s960").onclick = function () { return setViewportWidth(960); };
</script>
</body>
</html>

How to process backend coldfusion processing script response

I have implemented plupload using a ColdFusion backend script (available at https://gist.github.com/1116037).
The url attribute in the uploading page is url : '../upload.cfc?method=upload',
This simply calls a function within the cfc script. It works fine. This script also creates a variable called 'response' to hold information uploaded files.
The problem I am having is accessing the information held in the 'response' variable.
I would like to display that information in a table after the all the files have been uploaded to the server.
I am using the queue_widget for my needs’ think that an event (onComplete) needs to be triggered to call a function to process the information in variable, but I don't know how to do this.
I need to access the information held in the 'response' variable, preferably in ColdFusion code. Has anyone managed to get plupload working with ColdFusion yet?
Any help, guidance or coding would be appreciated.
Here is the full code I have used:
This is the main page - queue_widget.cfm
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Plupload - Queue widget example</title>
<link rel="stylesheet" href="../../js/jquery.plupload.queue/css/jquery.plupload.queue.css" type="text/css" media="screen" />
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<script type="text/javascript" src="../../js/plupload.js"></script>
<script type="text/javascript" src="../../js/plupload.flash.js"></script>
<script type="text/javascript" src="../../js/jquery.plupload.queue/jquery.plupload.queue.js"></script>
</head>
<body>
<h1>Queue widget example</h1>
<p>Shows the jQuery Plupload Queue widget and under different runtimes.</p>
<div style="float: left; margin-right: 20px">
<h3>Flash runtime</h3>
<div id="flash_uploader" style="width: 700px;">Your browser does not have Flash installed!</div>
</div>
<br style="clear: both" />
<cfoutput><cfset mnum=6></cfoutput>
<script type="text/javascript">
$(function() {
// Setup flash version
$("#flash_uploader").pluploadQueue({
// General settings
runtimes : 'flash',
url : '../upload.cfc?method=upload',
max_file_size : '1mb',
max_file_count: <cfoutput>#mnum#</cfoutput>, // You can limit the num of files that can be uploaded by manipulating the mnum variable above
unique_names : false,
multiple_queues : true,
multi_selection: true,
filters : [
{title : "Image files", extensions : "jpg,gif,png"}
],
init : {
FilesAdded: function(up, files) {
plupload.each(files, function(file) {
if (up.files.length > <cfoutput>#mnum#</cfoutput>) {
up.removeFile(file);
}
});
if (up.files.length >= <cfoutput>#mnum#</cfoutput>) {
$('#pickfiles').hide('slow');
}
},
FilesRemoved: function(up, files) {
if (up.files.length < 1) {
$('#pickfiles').fadeIn('slow');
}
}
},
resize : {width : 300, height : 10000, quality : 90}, // forces images to be resized to a width of 300px if wider than 300px
preinit: attachCallbacks,
UploadComplete: function(up, file, response) {
if ($("#result").length > 0){
$("#results").prepend(info.response);
} else {
$("#flash_uploader").after("<div id='results'>"+info.response+"</div>");
}
},
flash_swf_url : '../../js/plupload.flash.swf'
});
});
// Where should we go after upload
function attachCallbacks(Uploader){
Uploader.bind('FileUploaded', function(Up, File, response){
function IsJson(response) {
alert('Response from server: ' + response.file); // for testing only
counter++
var newRow = '<tr><td><input type="hidden" name="file_'+counter+'" value="'+response.file+'">'
newRow += 'Label the file: '+response.file+' <input type="text" name="filename_'+counter+'"></td></tr>'
$("#detail").append(newRow)
}});
};
</script>
<div id="results"></div>
<table id="detail">
</table>
<cfif IsDefined('response')><cfdump var="#response#"></cfif>
</body>
</html>
This the backend processing page - upload.cfc
<cfcomponent>
<cffunction name="upload" access="remote" returntype="struct" returnformat="json" output="false">
<cfscript>
var uploadDir = expandPath('/uploads/'); // should be a temp directory that you clear periodically to flush orphaned files
var uploadFile = uploadDir & arguments.NAME;
var response = {'result' = arguments.NAME, 'id' = 0};
var result = {};
</cfscript>
<!--- save file data from multi-part form.FILE --->
<cffile action="upload" result="result" filefield="FILE" destination="#uploadFile#" nameconflict="overwrite"/>
<cfscript>
// Example: you can return uploaded file data to client
response['size'] = result.fileSize;
response['type'] = result.contentType;
response['saved'] = result.fileWasSaved;
return response;
</cfscript>
</cffunction>
</cfcomponent>
You can try the above example here: [url] www.turn2cash.co.uk/plupload/examples/jquery/queue_widget.cfm [/url]
As mentioned above, the script works well with uploading (in this case) upto 6 images as determined by the mnum variable. What I need help with is with how to access the uploaded files (with page refresh) and be able to manipulate them.
I have setup an example (using cffileupload) of what I am after here [url] www turn2cash.co.uk/a/index.cfm [/url]
Although this works fine, it requires a page refresh, which is what I am trying to avoid.
Please provide any help you can.
Added 7 september 2012
I have tried both methods suggested by Miguel but did not achieve any positive outcomes. They actually caused the UI not to sow at all. However I found this and tried it:
preinit: attachCallbacks,
UploadComplete: function(up, file, response) {
if ($("#result").length > 0){
$("#results").prepend(info.response);
} else {
$("#flash_uploader").after("<div id='results'>"+info.response+"</div>");
}
},
flash_swf_url : '../../js/plupload.flash.swf'
});
});
// Where should we go after upload
function attachCallbacks(Uploader){
Uploader.bind('FileUploaded', function(Up, File, Response){
alert('Response from server: ' + Response.response);
});
};
</script>
I now get an alert displaying:
Response from server: {"saved":true,"result":"home.png","id":"0","size":"5988","type":"image"}
This at least prooves that the cfc script is working and the 'response' varialable is being returned. I still have no idea how to make use of this information as I have no knowledge of jquery, ajax or javascript. Please help if you can.
The link that I posted before has the example code. Sorry to post this as an answer but since I have no rep I cannot comment.
I think part of your confusion is in the request processing. You have this line of code at the bottom of your example.
<cfif IsDefined('response')><cfdump var="#response#"></cfif>
That will never fire because the coldfusion page is processed before you make the javascript ajax call to the server for the file upload. You will need to handle the response in javascript.
Are you seeing this alert from the attachCallbacks function?
alert('Response from server: ' + response.file); // for testing only

How do I save the position of draggable & resizeable elements?

I'm building a site which allows users to create an html page which can then be saved and shared on another site. I want them to be able to resize and drag the page elements. I can do this using jQuery, but I'm not sure how I then save that so that when the page is viewed elsewhere, it looks the same.
I haven't decided yet how to store the page info, but what I'm thinking is that I can store each element in the database along with its absolute position, and its contents. Does that sound like a good plan?
If so, how do I get the position for the div to pass to the php so that it can be saved?
Thanks.
JQueryUI Resizable has an event called resize that you can use:
var resposition = '';
$('#divresize').resizable({
//options...
resize: function(event,ui){
resposition = ui.position;
}
});
The same occurs with JQueryUI Draggable and its event drag:
var dragposition = '';
$('#divdrag').draggable({
// other options...
drag: function(event,ui){
dragposition = ui.position;
}
});
resposition and dragposition is going to be arrays. You can see it working here: http://jsbin.com/uvuzi5
EDIT: using a form, you can save dragposition and resposition into hidden inputs
var inputres = '<input type="hidden" id="resposition" value="'+resposition.left+','+resposition.top+'"/>'
$('#myform').append(inputres);
var inputdrag = '<input type="hidden" id="dragposition" value="'+dragposition.left+','+dragposition.top+'"/>'
$('#myform').append(inputdrag);
And in your PHP file to handle the form:
$dragposition = $_GET['dragposition'];
$resposition = $_GET['resposition'];
$dragposition = explode(',',$dragposition);
$resposition = explode(',',$resposition);
Finally, both variables should be arrays with top and left attributes:
$dragposition => [top,left] attributes from draggable
$resposition => [top,left] attributes from resizable
you have to save position at some where so that you can get position
details when next time you open page.
option 1: you can store html elements position details in "localStorage" its default browser storage.
Example: Demo
<!DOCTYPE html>
<html lang="en">
<head>
<title>Dashboard</title>
<!-- jQuery -->
<script src="vendor/jquery/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="dist/css/jquery-ui.min.css">
<script src="dist/js/jquery-ui.min.js"></script>
</head>
<body>
<script>
var positions = JSON.parse(localStorage.positions || "{}");
$(function() {
var d = $("[id=draggable]").attr("id", function(i) {
return "draggable_" + i
})
$.each(positions, function(id, pos) {
$("#" + id).css(pos)
})
d.draggable({
containment: "#wrapper",
scroll: false,
stop: function(event, ui) {
positions[this.id] = ui.position
localStorage.positions = JSON.stringify(positions)
}
});
});
</script>
<div id="wrapper">
<div id="draggable" class="ui-widget-content draggable" style="height:100px;width:100px;float:left">Div1</div>
<div id="draggable" class="ui-widget-content draggable" style="height:100px;width:100px;float:left">Div2</div>
<div id="draggable" class="ui-widget-content draggable" style="height:100px;width:100px;float:left">Div3</div>
</div>
</body>
</html>
option 2: you can store html elements position details in "your database"

Why can't I get the icons when I use jQueryUI with Google Ajax API within Jetpack?

I can't get any icons to be shown on a modal dialog box when I try to use jQueryUI via Google Ajax API. The icons do not appear but when I click on the locations where they are supposed to be the relevant functinality works (e.g. I can resize and close the modal dialog box). Here's the problematic screenshot and my code for Jetpack:
http://www.flickr.com/photos/64416865#N00/4303522684/
function testJQ() {
var doc = jetpack.tabs.focused.contentDocument;
var win = jetpack.tabs.focused.contentWindow;
$.get("http://ajax.googleapis.com/ajax/libs/jquery/1.4.0/jquery.min.js", function(js) {
var script = doc.createElement("script");
script.innerHTML = js;
doc.getElementsByTagName('HEAD')[0].appendChild(script);
$.get("http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js", function(js) {
var script = doc.createElement("script");
script.innerHTML = js;
doc.getElementsByTagName('HEAD')[0].appendChild(script);
$.get("http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/ui-lightness/jquery-ui.css", function(js) {
var style = doc.createElement("style");
style.innerHTML = js;
doc.getElementsByTagName('HEAD')[0].appendChild(style);
script = doc.createElement("script");
script.innerHTML = 'var myDialogFunc = function () {';
script.innerHTML += '$("<div id=dialog title=\\"Basic Dialog\\"> <p>The dialog window can be moved, resized and closed with the X icon.</p></div>").appendTo("body");';
script.innerHTML += '$("#dialog").dialog({'
script.innerHTML += ' bgiframe: true, height: 140, modal: true';
script.innerHTML += ' });';
script.innerHTML += '};';
doc.body.appendChild(script);
win.wrappedJSObject['myDialogFunc']();
});
});
});
}
On the other hand, in a simple html document I can use Google Ajax API, load jquery and jQueryUI and get the icons correct without any problems. Here's the screenshot and source code that works as I expect:
http://www.flickr.com/photos/64416865#N00/4303522672/
<html>
<head>
<script src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
var myDialogFunc = function () {
$("#dialog").dialog({
bgiframe: true,
height: 140,
modal: true
});
};
// Load jQuery
google.load("jquery", "1.4.0");
google.load("jqueryui", "1.7.2");
google.setOnLoadCallback(function() {
myDialogFunc();
});
</script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/ui-lightness/jquery-ui.css" type="text/css" media="all" />
</head>
<body>
<div id="dialog" title="Basic Dialog">
<p>The dialog window can be moved, resized and closed with the X icon.</p>
</div>
</body>
Any ideas about why I can't get the icons in my Jetpack version?
Code below solves my problem:
js = js.replace("url(", "url(http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/ui-lightness/", "g");
style.innerHTML = js;

Resources