A Meteor client code displays a canvas for user signature and option to save it to the user collection to be fetched later for inserting into future html report pages which will also need to be signed.
What is the general outline to achieve this and how to do it?
//client
let imgData = ctx.getImageData(0, 0, width, height);
Meteor.call('saveImageToUser', imgData);
//server
Meteor.methods({
'saveImageToUser': (img) => {
Meteor.users.update(userId, {
signature: img
})
}
});
I've done the same thing in one of my web apps.
My html:
<canvas id="simple_sketch" width="400" height="400"></canvas>
My client js :
var canvas = $(#simple_sketch")[0].toDataURL();
Meteor.call('saveImageToUser', canvas);
My method (remember due to meteor's user object you must save it in the profile object of the user.
'saveImageToUser' : img => {
Meteor.users.update(userId, {
'profile.signature' : img
})
}
Related
I'd like to use form.io in order to allow my admin users to create a new forms but I want save all data into my database, not in form.io platform. Is it possible?
I want use form builder but at save time I want save the form structure into my database.
I don't understand if this option is possible.
Thanks
Yes.
Step 1: Store your components in your database. If you use the form builder, you can get them by a call to builder.schema.
Step 2: Retrieve your components from your database and render the form.
Step 3: Save the data to your DB.
components = {{component string from DB}}
let formio = new Formio.createForm(document.getElementById(element),
components,
{
saveDraft: true,
readOnly: ((readonly) ? readonly : false)
}
).then(function (form) {
if (data) {
var subm = JSON.parse(data)
form.submission = { data: subm };
}
form.on('submit', function (submission) {
//Submission Code
});
form.on('change', function (x) {
//Change Code
})
form.on('error', (errors) => {
//Error Code
})
form.on("render", function () {
//Any Render Overrides?
})
}).catch(function (ex) {
});
Some of this stuff is well documented. Some - not so much. Lots of trial and error. (Mostly error).
Something similar is what works for me. Note this is for saving the schema for the Form Builder. This schema can be deserialized and used as a source for the Form Renderer
#uglyCodeSry
JavaScript
var form;
var formTemplateToSave; // this is the serialized form template to save
window.onload = function() {
var builder = Formio.builder(document.getElementById('builder'), {}, {builder: {}
}).then((_form) => {
form = _form;
form.on('change', function(payload) {
formTemplateToSave = JSON.stringify(form.schema, null, 4);
});
formTemplateToSave = JSON.stringify(form.schema, null, 4);
});
};
HTML
<div>
<div id='builder'></div>
</div>
Don't forget to include the libraries (as well as your usual jquery stuff)
<link rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css'>
<link rel='stylesheet' href='https://cdn.form.io/formiojs/formio.full.min.css'>
<script src='https://cdn.form.io/formiojs/formio.full.min.js'></script>
You can then save the formTemplateToSave variable as the JSON to rehydrate your forms
I am taking pic from camera and uploading to server , then returning the url of picture from server.But previous picture is still there.Image is not updating.
You have to create a variable in TYPESCRIPT something like :
path:String = "";
then the function to take a photo
takePicture(){
Camera.getPicture({
destinationType: Camera.DestinationType.DATA_URL,
targetWidth: xxx,
targetHeight: yyy
}).then((imageData) => {
// imageData is a base64 encoded string,
this.path = "data:image/jpeg;base64," + imageData;
//create a function here to send the photo and the return will be the link
this.path = getServerLink();
}, (err) => {
console.log(err);
});
}
then in HTML
<img src="{{path}}"/>
<!--or -->
<img [src]="path" *ngIf="path" />
I am able to upload images from my desktop to an Angular based Web Application overlayed on SharePoint without issue, but if I upload from a Mobile phone, such as an iPhone, using the take "Take Photo or Video" or "Photo Library" function, it causes the image to be sideways when taken in portrait or upside down when taken in landscape. Here is my current upload function. Any clues/have others had the same issues uploading to Mobile Web Applications from iPhones/Mobile Phones to a SharePoint library?
Here is my upload function:
// Upload of images
$scope.upload = function () {
//console.log($scope.files);
if (document.getElementById("file").files.length === 0) {
alert('No file was selected');
return;
}
var parts = document.getElementById("file").value.split("\\");
var uploadedfilename = parts[parts.length - 1];
var basefilename = uploadedfilename.split(".")[0];
var fileextension = uploadedfilename.split(".")[1];
var currentdate = new Date();
var formatteddate = $filter('date')(new Date(currentdate), 'MMddyy-hmmssa');
var filename = basefilename + formatteddate + '.' + fileextension;
var file = document.getElementById("file").files[0];
uploadFileSync("/sites/asite", "Images", filename, file);
}
//Upload file synchronously
function uploadFileSync(spWebUrl, library, filename, file)
{
console.log(filename);
var reader = new FileReader();
reader.onloadend = function(evt)
{
if (evt.target.readyState == FileReader.DONE)
{
var buffer = evt.target.result;
var completeUrl = spWebUrl
+ "/_api/web/lists/getByTitle('"+ library +"')"
+ "/RootFolder/Files/add(url='"+ filename +"',overwrite='true')?"
+ "#TargetLibrary='"+library+"'&#TargetFileName='"+ filename +"'";
$.ajax({
url: completeUrl,
type: "POST",
data: buffer,
async: false,
processData: false,
headers: {
"accept": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"content-length": buffer.byteLength
},
complete: function (data) {
console.log(data);
},
error: function (err) {
alert('failed');
}
});
}
};
reader.readAsArrayBuffer(file);
}
The output of these is just pushed into an array for use in an Angular UI Carousel:
// Control of Image Carousel
$scope.myInterval = 0;
// Population of carousel
$scope.slides = [];
appImages.query({
$select: 'FileLeafRef,ID,Created,Title,UniqueId',
$filter: 'ReportId eq ' + $routeParams.Id + ' and DisplayinReport eq 1',
}, function (getimageinfo) {
// Data is within an object of "value"
var image = getimageinfo.value;
// Iterate over item and get ID
angular.forEach(image, function (imagevalue, imagekey) {
$scope.slides.push({
image: '/sites/asite/Images/' + imagevalue.FileLeafRef,
});
});
});
The image carousel is on page as follows:
<div style="height: 305px; width: 300px">
<carousel interval="myInterval">
<slide ng-repeat="slide in slides" active="slide.active">
<img ng-src="{{slide.image}}" style="margin:auto;height:300px">
<div class="carousel-caption">
<h4>Slide {{$index}}</h4>
<p>{{slide.text}}</p>
</div>
</slide>
</carousel>
</div>
IMPORTANT: The images are sideways and upside down upon upload to the SharePoint library, so irrespective of outputting them, they seem to be misoriented when they hit the destination library I am using as a source to display on page.
How do I upload the images so SharePoint respects the EXIF data/orientation?
It may be related to EXIF. See JS Client-Side Exif Orientation: Rotate and Mirror JPEG Images
If you want a better answer, we will need the code which show the image, and the code server side.
UPDATE : I'm not an expert at all on SharePoint, but you can found a lot about it in the SharePoint Stack Exchange. For example, https://sharepoint.stackexchange.com/questions/131552/sharepoint-rotating-pictures-in-library, should do the trick.
To sum up a little : in your case, their could be a lot of cases to study. So, I recommended you auto-correct the exif, and then permit to your user to correct it if the auto-correct was wrong. Their is a lot of tools to do that. If you want to do it server-side, look at the link above, and if you want to do it on the client side, you could use JS-Load-Image for example.
I am using sage cell to convert html to math stuff
Template.home.rendered = function(){
\\ apply sagecell and mathjax
}
However, the content that are rendered comes from mongo, so it's sometimes loaded after sage cell is applied to it. I can do something like this
Template.home.rendered = function(){
Deps.autorun(function(){
if (Content.findOne({_id: ...})){
\\ apply sagecell and mathjax
}
});
}
It's better but still doesn't work all the time. Is there other things I can use to detect the content is completely rendered?
Edited with new response:
<template name='pendingAnswer'>
The answer to your question, coming back whenever, is:
{{>answer}}
</template>
<template name='answer'>
{{fromSage}}
</template>
Template.answer.helpers({
fromSage: function () {
Session.get('fromSage');
}
});
Invoked whenever - from a button, from navigating to the page, on blur...
function GetAnswerFromSage(data) {
callHTTP(website,data, callbackFromSage)
}
function callbackFromSage(err, data) {
if (err) then log(err);
Session.set('fromSage', data);
}
Earlier: try transform upon retrieval of mongo:
From Meteor Doc
// An Animal class that takes a document in its constructor
Animal = function (doc) {
_.extend(this, doc);
};
_.extend(Animal.prototype, {
makeNoise: function () {
console.log(this.sound);
}
});
// Define a Collection that uses Animal as its document
Animals = new Meteor.Collection("Animals", {
transform: function (doc) { return new Animal(doc); }
});
// Create an Animal and call its makeNoise method
Animals.insert({name: "raptor", sound: "roar"});
Animals.findOne({name: "raptor"}).makeNoise(); // prints "roar"
The script
<script type='text/javascript' src="http://sagecell.sagemath.org/static/embedded_sagecell.js"></script>
that is supposed to be in the head needs to be removed and instead be loaded after the content is completely loaded like so:
Template.content.rendered = function(){
// sage
Deps.autorun(function(){
if (Session.get('contentChanged')){
// loading this script causes mathjax to run
$.getScript("http://sagecell.sagemath.org/static/embedded_sagecell.js", function(d, textStatus){
if (textStatus=='success'){
// this converts <div class='compute'> to a sage cell
sagecell.makeSagecell({
inputLocation: 'div.compute',
evalButtonText: 'Evaluate',
hide: ['editorToggle']
});
}
})
}
})
and if I go from 1 content template to another content template, it seems that nothing is rerendered and so the mathjax was not applied. The only fix I can think is to force a page reload:
Template.content.events({
'click a': function(evt){
evt.preventDefault();
location.href = evt.currentTarget.href;
}
})
which makes the site much slower, unfortunately.
How can I drop items (like image, or other object from other canvas) into canvas which is managed by fabricjs? I have found many examples how to move items inside canvas but I would like to drag and drop item from outer element into canvas.
Since you asked for an example and I haven't tried it out myself yet, here goes:
Example Fiddle
Markup
<div id="images">
<img draggable="true" src="http://i.imgur.com/8rmMZI3.jpg" width="250" height="250"></img>
<img draggable="true" src="http://i.imgur.com/q9aLMza.png" width="252" height="295"></img>
<img draggable="true" src="http://i.imgur.com/wMU4SFn.jpg" width="238" height="319"></img>
</div>
<div id="canvas-container">
<canvas id="canvas" width="800" height="600"></canvas>
</div>
JS Breakdown
1. Fabric.canvas instance
First we want our canvas, of course:
var canvas = new fabric.Canvas('c');
2. Feature Detection (optional)
Not sure this is necessary, since the fact that you have a canvas makes it very likely that the browser has Drag and Drop as well. Were you to use it, you can do so like this, using Modernizr:
if (Modernizr.draganddrop) {
// Browser supports HTML5 DnD.
// Bind the event listeners for the image elements
// Bind the event listeners for the canvas
} else {
// Replace with a fallback to a library solution.
alert("This browser doesn't support the HTML5 Drag and Drop API.");
}
3. Events
Again, unlike the source article I below, the source and target elements are different (in that articles's example, you just move divs around within the same parent container), so I failed to notice that some of the events are meant for the element being dragged, but most are bound to the element into which you are dropping.
NOTE: I know this is technically a question about Fabric.js, but it's really kind of a question about Drag and Drop in the context of adding objects to a <canvas> with Fabric.js, which is why I'm going a bit more in depth about the DnD stuff now.
For the <img>
dragstart (I added a class here to lower the opacity)
dragend (and removed that class here)
For #canvas-container:
dragenter (added a class to give the canvas container that nifty dotted line)
dragover: Here you can set the event.dataTransfer.dropEffect property to show one of the native cursor types. The default would be 'move' here, but I set it to 'copy' since I don't actually remove the <img> element (in fact in the fiddle you can, for example create several McClures).
dragleave (removed the dotted line here)
drop: The handler for this event creates and adds the fabric.Image object (see the fiddle).
if (Modernizr.draganddrop) {
// Browser supports HTML5 DnD.
// Bind the event listeners for the image elements
var images = document.querySelectorAll('#images img');
[].forEach.call(images, function (img) {
img.addEventListener('dragstart', handleDragStart, false);
img.addEventListener('dragend', handleDragEnd, false);
});
// Bind the event listeners for the canvas
var canvasContainer = document.getElementById('canvas-container');
canvasContainer.addEventListener('dragenter', handleDragEnter, false);
canvasContainer.addEventListener('dragover', handleDragOver, false);
canvasContainer.addEventListener('dragleave', handleDragLeave, false);
canvasContainer.addEventListener('drop', handleDrop, false);
} else {
// Replace with a fallback to a library solution.
alert("This browser doesn't support the HTML5 Drag and Drop API.");
}
Sources:
HTML5 Rocks - Native HTML5 Drag and Drop
Modernizr
Web Platform Docs > DOM > Properties - dropEffect
Web Platform Docs > DOM > Events
dragstart
dragend
dragenter
dragover
dragleave
drop
I had gone through fiddle of #natchiketa, And fixed the problem , just check this fiddle..
http://jsfiddle.net/Ahammadalipk/w8kkc/185/
window.onload = function () {
var canvas = new fabric.Canvas('canvas');
/*
NOTE: the start and end handlers are events for the <img> elements; the rest are bound to
the canvas container.
*/
function handleDragStart(e) {
[].forEach.call(images, function (img) {
img.classList.remove('img_dragging');
});
this.classList.add('img_dragging');
}
function handleDragOver(e) {
if (e.preventDefault) {
e.preventDefault();
}
e.dataTransfer.dropEffect = 'copy';
return false;
}
function handleDragEnter(e) {
this.classList.add('over');
}
function handleDragLeave(e) {
this.classList.remove('over');
}
function handleDrop(e) {
if (e.stopPropagation) {
e.stopPropagation(); // stops the browser from redirecting.
}
var img = document.querySelector('#images img.img_dragging');
var newImage = new fabric.Image(img, {
width: img.width,
height: img.height,
// Set the center of the new object based on the event coordinates relative
// to the canvas container.
left: e.layerX,
top: e.layerY
});
newImage.hasControls = newImage.hasBorders = false;
canvas.add(newImage);
return false;
}
function handleDragEnd(e) {
// this/e.target is the source node.
[].forEach.call(images, function (img) {
img.classList.remove('img_dragging');
});
}
if (Modernizr.draganddrop) {
var images = document.querySelectorAll('#images img');
[].forEach.call(images, function (img) {
img.addEventListener('dragstart', handleDragStart, false);
img.addEventListener('dragend', handleDragEnd, false);
});
var canvasContainer = document.getElementById("canvas-container");
canvasContainer.addEventListener('dragenter', handleDragEnter, false);
canvasContainer.addEventListener('dragover', handleDragOver, false);
canvasContainer.addEventListener('dragleave', handleDragLeave, false);
canvasContainer.addEventListener('drop', handleDrop, false);
} else {
alert("This browser doesn't support the HTML5 Drag and Drop API.");
}
}
Thanks
Well, the question is quite old^^
I have updateted the fiddle, no it will work in Firefox as well.
Fiddle
function handleDrop(e) {
// this / e.target is current target element.
e.preventDefault(); //I've altert this line for FireFox
As far as I understand, drag and drop is not already provided by fabricjs,
fiddling it will be quite interesting.
Well I m new to javascript and fabricJS but I think this fiddle might help
fiddle
html code
<div class="img_cont">
<img class="img" id="ele1" draggable="true" ondragstart="dragElement(event)" src="https://webkit.org/wp-content/uploads/STP-300x300.png">
<img class="img" id="ele2" draggable="true" ondragstart="dragElement(event)" src="https://webkit.org/wp-content/uploads/ephy-webkit-graphic.png">
<img class="img" id="ele3" draggable="true" ondragstart="dragElement(event)" src="https://res.cloudinary.com/css-tricks/image/upload/w_600,q_auto,f_auto/buysellads/uu/7/112766/1646327381-MC_CSSTricks_Logo_600x600-_1_.png">
<img class="img" id="ele4" draggable="true" ondragstart="dragElement(event)" src="https://miro.medium.com/max/1400/1*9hd_8qR0CMZ8L0pVbFLjDw.png">
</div>
<br>
<div id="canvas_cont" ondragover="allowDrop(event)" ondrop="dropElement(event)">
<canvas id="canvas" width="650" height="350" ></canvas>
</div>
javascript code
// allowDrop function called on ondragover event.
function allowDrop(e) {
e.preventDefault();
}
//dragElement function called on ondrag event.
function dragElement(e) {
e.dataTransfer.setData("id", e.target.id); //transfer the "data" i.e. id of the target dragged.
}
//Initializing fabric canvas on window load event.
var canvas;
window.onload = function(){
canvas = new fabric.Canvas(document.getElementById("canvas"));
}
//dropElement function called on ondrop event.
function dropElement(e) {
e.preventDefault();
var data = e.dataTransfer.getData("id"); //receiving the "data" i.e. id of the target dropped.
var imag = document.getElementById(data); //getting the target image info through its id.
var img = new fabric.Image(imag, { //initializing the fabric image.
left: e.layerX - 80, //positioning the target on exact position of mouse event drop through event.layerX,Y.
top: e.layerY - 40,
});
img.scaleToWidth(imag.width); //scaling the image height and width with target height and width, scaleToWidth, scaleToHeight fabric inbuilt function.
img.scaleToHeight(imag.height);
canvas.add(img);
}
The accepted answer no longer works.
This is for drag and drop from desktop using the dataTransfer interface.
canvas.on('drop', function(event) {
// prevent the file to open in new tab
event.e.stopPropagation();
event.e.stopImmediatePropagation();
event.e.preventDefault();
// Use DataTransfer interface to access the file(s)
if(event.e.dataTransfer.files.length > 0){
var files = event.e.dataTransfer.files;
for (var i = 0, f; f = files[i]; i++) {
// Only process image files.
if (f.type.match('image.*')) {
// Read the File objects in this FileList.
var reader = new FileReader();
// listener for the onload event
reader.onload = function(evt) {
// put image on canvas
fabric.Image.fromURL(evt.target.result, function(obj) {
obj.scaleToHeight(canvas.height);
obj.set('strokeWidth',0);
canvas.add(obj);
});
};
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
}
}
});
Resources
https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop