Unable import existing data in jSignature - javascript

This is the code I'm saving my jSignature value in my database:
var datapair = $('.sign-wrapper').jSignature();
datapair.bind('change', function(e){
var data = datapair.jSignature("getData", "svgbase64");
var i = new Image()
i.src = "data:" + data[0] + "," + data[1];
$(this).prev('input').val(i.src);
});
So I'm having following value in my DB:
data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj48c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4xIiB3aWR0aD0iODkiIGhlaWdodD0iMTEyIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNIDEgMTExIGMgMC4wNCAtMC4xNCAxLjAyIC01LjQ1IDIgLTggYyAyLjM0IC02LjA4IDUuOSAtMTEuODcgOCAtMTggYyAxLjg2IC01LjQ0IDMuMDkgLTExLjIyIDQgLTE3IGMgMS4xIC02Ljk4IDAuODggLTEzLjk4IDIgLTIxIGMgMS4yNSAtNy44MyAzLjA0IC0xNS4zOSA1IC0yMyBjIDAuNzEgLTIuNzYgMS43NiAtNS41MiAzIC04IGMgMS4wNSAtMi4wOSAyLjUyIC00LjA4IDQgLTYgYyAxLjg5IC0yLjQ2IDMuOTIgLTQuOTIgNiAtNyBjIDAuODEgLTAuODEgMi4yNiAtMi4yMiAzIC0yIGMgMS43NyAwLjUzIDUuMzcgMyA3IDUgYyAyLjM3IDIuOTEgNC40NiA3LjEzIDYgMTEgYyA1LjQ2IDEzLjc5IDkuMzIgMjguNTIgMTUgNDIgYyAyLjIzIDUuMjkgNi4zOCA5Ljc2IDkgMTUgYyAzLjQyIDYuODQgNS43NiAxNC43NiA5IDIxIGwgNCA0Ii8+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgZD0iTSAyMCA2NCBjIDAuMTEgLTAuMTIgMy43MyAtNS40IDYgLTcgYyAyLjk4IC0yLjEgNy4yMSAtMy44NSAxMSAtNSBjIDcuMDcgLTIuMTQgMTQuNzggLTMuNzEgMjIgLTUgYyAxLjkyIC0wLjM0IDYgMCA2IDAiLz48L3N2Zz4=
So while reloading the page I'm having the above base64 image data url in a hidden variable.
I tried to load the data to the existing signature canvas using below code:
// If value exist load existing
var src = $(this).prev('input').val();
if(src != '') {
datapair.jSignature("importData", src);
}
But it is not working and I am getting following error in console:
Uncaught Error: jSignature is unable to find import plugin with for
format 'image/svg+xml;base64'

The problem occurs when your data is not recognized by the plugin.
The reason why it throws an error is, the format 'image/svg+xml;base64' is not supported by the importer, there is only an exporter support for it.
Reference:
https://github.com/brinley/jSignature#data-import--export-and-plugins
I suggest you store the data using base30 because there is support for both export and import.
var data = datapair.jSignature("getData", "base30 ");

setData takes two arguments - data object, data format name. When data object is a string formatted in data-url pattern you don't need to specify the data dormat name. The data format name (mime) will be implied from the data-url prefix. See example below for that. Returns (in a traditional jQuery chainable way) jQuery object ref to the element onto which the plugin was applied.
You can store the value in base64 and load it. I load the value in base64 in an input and through Jquery I load it in the object.
// Creo el objeto de firma.
$("#jq_sig").jSignature
({
// width/height of signature pad
width: 497,
height: 200,
// Format bootstrap 4
cssclass: "bg-light border",
lineWidth: 2,
color: "black",
});
// I take the value of the form field that I previously loaded with PHP.
var firma = $('#form input[name=firma]').val();
if (firma.length > 0)
{
$("#jq_sig").jSignature("setData", 'data:image/png;base64,' + firma);
console.log('Signature loaded.');
}
else
{
console.log('Signature not loaded.');
}
You can save to your database in any format. Then you tell 'setdata' what kind of format it is.

Related

Convert XML response to useful data

I am interacting with a server (Geoserver) by sending a request to get some data.
The data is geographic information about some features.
Here is how I am doing it :
function filter() {
var demande = new XMLHttpRequest();
var url ='http://localhost:8080/geoserver/wfs?request=GetFeature&version=1.1.0&typeName=topp:refer_22&propertyName=Name,maticha&outputFormat=GML2&FILTER=%3CFilter%20xmlns=%22http://www.opengis.net/ogc%22%3E%3CPropertyIsBetween%3E%3CPropertyName%3Etopp:maticha%3C/PropertyName%3E%3CLowerBoundary%3E%3CLiteral%3E4500%3C/Literal%3E%3C/LowerBoundary%3E%3CUpperBoundary%3E%3CLiteral%3E5000%3C/Literal%3E%3C/UpperBoundary%3E%3C/PropertyIsBetween%3E%3C/Filter%3E'
demande.open("GET", url);
demande.onload=() => {
console.log(demande.response);
}
demande.send();
}
The request is to get data that match a condition ( x <data< some value )
I have a button when I click on it, the function filter() run to send and get the response of the xmlhttprequest.
Everything is working fine except that the result I get in the console is long :
<wfs:FeatureCollection
xmlns="http://www.opengis.net/wfs"
xmlns:wfs="http://www.opengis.net/wfs"
xmlns:gml="http://www.opengis.net/gml"
xmlns:topp="http://www.openplans.org/topp"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://localhost:8080/geoserver/schemas/wfs/1.0.0/WFS-basic.xsd http://www.openplans.org/topp http://localhost:8080/geoserver/wfs?service=WFS&version=1.0.0&request=DescribeFeatureType&typeName=topp%3Arefer_22,topp%3Arefer_22">
<gml:boundedBy>
<gml:null>unknown</gml:null>
</gml:boundedBy>
<gml:featureMember>
<topp:refer_22 fid="refer_22.9">
<topp:the_geom>
<gml:MultiPolygon srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
<gml:polygonMember>
<gml:Polygon>
<gml:outerBoundaryIs>
<gml:LinearRing>
<gml:coordinates
xmlns:gml="http://www.opengis.net/gml" decimal="." cs="," ts=" ">34.69647,-1.919276 34.69651,-1.918997 34.697229,-1.919003 34.697317,-1.918058 34.697418,-1.91713 34.697462,-1.91653 34.697568,-1.915618 34.697837,-1.914641 34.698261,-1.913174 34.698614,-1.912023 34.699005,-1.910633 34.697456,-1.909919 34.696871,-1.909666 34.695711,-1.90917 34.694404,-1.908606 34.693794,-1.908351 34.69322,-1.908068 34.69202,-1.907558 34.691892,-1.908461 34.691702,-1.909658 34.69146,-1.910865 34.691429,-1.911192 34.691252,-1.912179 34.691063,-1.913338 34.690979,-1.913724 34.690851,-1.914132 34.690772,-1.914518 34.690644,-1.915205 34.690489,-1.915998 34.690145,-1.91764 34.690017,-1.918244 34.689918,-1.918702 34.689845,-1.919067 34.6897,-1.919978 34.689386,-1.92124 34.689422,-1.923584 34.69097,-1.923686 34.692518,-1.923552 34.6928,-1.923519 34.69329,-1.923428 34.693444,-1.923401 34.694662,-1.923037 34.695372,-1.922404 34.695663,-1.922034 34.695943,-1.921564 34.696161,-1.921111 34.696298,-1.920569 34.696399,-1.920022 34.696444,-1.91966 34.69647,-1.919276
</gml:coordinates>
</gml:LinearRing>
</gml:outerBoundaryIs>
</gml:Polygon>
</gml:polygonMember>
</gml:MultiPolygon>
</topp:the_geom>
<topp:Name>OUJ-DK9</topp:Name>
<topp:maticha>4500</topp:maticha>
</topp:refer_22>
</gml:featureMember>
</wfs:FeatureCollection>
As you can see, this above is the result in string format. There is a 'Geometry' field (the_geom), a 'name' field and a field called 'maticha' (used to filter the data).
This is good but I would rather get a SON format for the data or some kind of array where I can access it.
For example, I want to be able able to write :
var geometry = response[..]
to get the list of coordinates of the returned result.
Is there any way to that ??
Geoserver supports different result formats with the outputFormat parameter. Your request sets it to GML2, which is XML. JSON output is also supported.
Since your request URL is really hard to read and to manipulate, I recommend that you use a UrlSearchParams object instead of trying to manage the URL parameters manually in one huge messy line.
Here is how I would implement your filter() function.
function filter(lowerBoundary, upperBoundary, onSuccess) {
var params = new URLSearchParams();
params.append('request', 'GetFeature');
params.append('version', '1.1.0');
params.append('typeName', 'topp:refer_22');
params.append('propertyName', 'Name,maticha');
params.append('outputFormat', 'application/json');
params.append('filter', `<Filter xmlns="http://www.opengis.net/ogc">
<PropertyIsBetween>
<PropertyName>topp:maticha</PropertyName>
<LowerBoundary><Literal>${lowerBoundary}</Literal></LowerBoundary>
<UpperBoundary><Literal>${upperBoundary}</Literal></UpperBoundary>
</PropertyIsBetween>
</Filter>`);
var demande = new XmlHttpRequest();
demande.open("GET", 'http://localhost:8080/geoserver/wfs?' + params.toString());
demande.onload = () => onSuccess(JSON.parse(demande.response));
demande.send();
}
// later ...
filter(4000, 5000, (data) => {
console.log(data):
});
There also seems to be an easier filter syntax available, see ECQL.

TF.js load object detection model in model.json format in browser

I've trained a .pb object detection model in python using Colab and converted it to the model.json format using the TensorFlow converter. I need to load this model inside the browser (no Node.js!) and run inference there.
This is the structure of my model folder the TensorFlow converter produced:
model
| - model.json
| - labels.json
| - group1-shard1of2.bin
| - group1-shard2of2.bin
The Tensorflow documentation suggest the following to load such a model:
const model = await tf.loadGraphModel('model/model.json');
or
const model = await tf.loadLayersModel('model/model.json');
I am using the tf.loadGraphModel function. Loading the model works flawlessly, but when I try to run inference with it using this code:
// detect objects in the image.
const img = document.getElementById('img');
model.predict(img).then(predictions => {
console.log('Predictions: ');
console.log(predictions);
});
it throws the following error:
Uncaught (in promise) Error: The dict provided in model.execute(dict) has keys [...] that are not part of graph
at e.t.checkInputs (graph_executor.js:607)
at e.t.execute (graph_executor.js:193)
at e.t.execute (graph_model.js:338)
at e.t.predict (graph_model.js:291)
at predictImages (detector.php:39)
Am I using the wrong loading function, did the model loading process fail (even though it didn't throw any errors?) or is the inference function wrong?
Thanks in advance for your support!
EDIT: After using #edkeveked's suggestion to convert the image to a tensor first using this code:
const tensor = tf.browser.fromPixels(img);
and running inference using this:
model.predict(tensor.expandDims(0));
I got this error message:
Uncaught (in promise) Error: This execution contains the node 'Preprocessor/map/while/Exit_2', which has the dynamic op 'Exit'. Please use model.executeAsync() instead. Alternatively, to avoid the dynamic ops, specify the inputs [Preprocessor/map/TensorArrayStack/TensorArrayGatherV3]
at e.t.compile (graph_executor.js:162)
at e.t.execute (graph_executor.js:212)
at e.t.execute (graph_model.js:338)
at e.t.predict (graph_model.js:291)
at predictImages (detector.php:38)
After replacing model.predict() with model.executeAsync(), it returned a result that was not what I expected to get from an object detection model:
detector.php:40 (2) [e, e]0: e {kept: false, isDisposedInternal: false, shape: Array(3), dtype: "float32", size: 3834, …}1: e {kept: false, isDisposedInternal: false, shape: Array(4), dtype: "float32", size: 7668, …}length: 2__proto__: Array(0)
This is my complete code so far (images added in HTML using PHP):
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs#2.8.3/dist/tf.min.js"></script>
<!-- Load the coco-ssd model. -->
<script src="https://cdn.jsdelivr.net/npm/#tensorflow-models/coco-ssd#1.1.0"></script>
<script>
async function predictImages() { // async
console.log("loading model");
// Load the model.
const model = await tf.loadGraphModel('model/model.json');
console.log("model loaded.");
// predict for all images
for (let i = 0; i <= 4; i++) {
const img = document.getElementById('img' + i); // check if image exists if (img
if (img != null) {
console.log("doc exists: " + 'img' + i);
const tensor = tf.browser.fromPixels(img);
model.executeAsync(tensor.expandDims(0)).then(predictions => {
console.log('Predictions: ');
console.log(predictions);
});
} else {
break;
}
}
}
predictImages();
</script>
model.predict expects a tensor but it is given an HTMLImageElement. First a tensor needs to be constructed from the HTMLImageElement.
const tensor = tf.browser.fromPixels(img)
And then the tensor can be used as the parameter to model.predict
model.predict(tensor) // returns a 3d
Last but not the least is to make sure that the tensor shape is the one expected by the model (3d or 4d). If the model expects a 4d, then it should rather be
model.predict(tensor.expandDims(0))

Bytes to image from Parse.com

I'm trying to convert a Parse.com object into an image with Javascript. The object is of the type Bytes, and I can't convert it in any way. Can someone give me an example of how to turn it into a functional URL? I try to access it but it just keeps crashing.
Edit:
getURL: function () {
var query = new Parse.Query("Token");
query.limit(20);
query.find().then(this.handleCallback.bind(this));
},
handleCallback: function (objects) {
for (var i = 0; i < objects.length; i++) {
this.tokenSearch[i] = {
imgURL: "data:image/png;base64," + objects[i].get("pic")
};
}
}
I have tried objects[i].get("pic").url(), objects[i].get("pic").toString('base64') and some other stuff, but it won't work!
If you want to store images and later have a URL you can load, you should switch to the File data type instead of pushing just a byte array. The documentation you linked recommends the following:
There are two ways to store binary data. The Bytes type allows you to associate NSData/bytes[] types directly on a PFObject. This is recommended only for small pieces of binary-encoded data. For actual files (images, documents, etc.), the File type can be used by instantiating a PFFile/ParseFile and setting it on a field.
You have stored the actual byte array into the pic column of your Parse class. Therefore, that's all you get. If you chose instead to store it as a File (PFFile in iOS/OSX, ParseFile in Android), you could do what you're trying to do. As it is, Parse is merely storing the bytes as it would store any other data, such as a Date or a String. There's no URL data associated with it.
Here's how you can create and upload a PFFile from an iOS device:
- (void)updateloadImage:(UIImage *)image {
PFFile *file = [PFFile fileWithData:UIImagePNGRepresentation(image)];
PFObject *newToken = [PFObject objectWithClassName:#"Token"];
newToken[#"pic"] = file;
[newToken saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
// Do real error handling here
// Now, you have :
// 1. The "pic" saved to Parse as a PFFile
// 2. The "token" saved to Parse as a PFObject
// 3. The "pic" stored as a property on the "token"
}
];
}
Once you have it stored that way on Parse, you would access it in the JavaScript SDK something like this:
function getURL() {
var query = new Parse.Query("Token");
query.limit(20);
query.find().then(function (objects) {
for (var i = 0; i < objects.length; i = i + 1) {
this.tokenSearch[i] = {imgURL: objects[i].get("pic").url()};
}
});
}

Why does my dojo xhrPost request's response always end up in error handler?

My javascript:
var params = {};
params.selectedCurrency = 'USD';
params.orderIdForTax = '500001';
var xhrArgs1 = {
url : 'UpdateCurrencyCmd',
handleAs : 'text',
content : params,
preventCache:false,
load:function(data){
alert('success!');
},
error: function(error){
alert(error);
//the alert says 'SyntaxError: syntax error'
},
timeout:100000
};
dojo.xhrPost(xhrArgs1);
I tried debugging with firebug, i do get the appropriate response (i think). Here it is;
/*
{
"orderIdForTax": ["500001"],
"selectedCurrency": ["USD"]
}
*/
The comments /* and */ are somehow embedded automatically cuz the url im hitting with xhrPost is actually a command class on ibm's websphere commerce environment. Can anyone tell me what am i doing wrong here?
Server code
public void performExecute() throws ECException {
try{
super.performExecute();
double taxTotal;
System.out.println("Updating currency in UpdateCurrencyCmd...");
GlobalizationContext cntxt = (GlobalizationContext) getCommandContext().getContext(GlobalizationContext.CONTEXT_NAME);
if(requestProperties.containsKey("selectedCurrency"))
selectedCurrency = requestProperties.getString("selectedCurrency");
else
selectedCurrency = cntxt.getCurrency();
if(requestProperties.containsKey("orderIdForTax"))
orderId = requestProperties.getString("orderIdForTax");
OrderAccessBean orderBean = new OrderAccessBean();
cntxt.setCurrency(selectedCurrency.toUpperCase());
orderBean.setInitKey_orderId(orderId);
orderBean.refreshCopyHelper();
orderBean.setCurrency(selectedCurrency.toUpperCase());
orderBean.commitCopyHelper();
TypedProperty rspProp = new TypedProperty();
rspProp.put(ECConstants.EC_VIEWTASKNAME, "AjaxActionResponse");
setResponseProperties(rspProp);
}catch(Exception e){
System.out.println("Error: " + e.getMessage() );
}
}
The problem was with my client side code, weirdly.
load:function(data){
data = data.replace("/*", "");
data = data.replace("*/", "");
var obj = eval('(' + data + ')');
alert('Success');
}
Its weird but this worked. Lol.
I guess the problem is with coment-filtering option of handle as method.
The response should be comment filered as below.
See tha AjaxActionResponse.jsp (WCS)
vailable Handlers
There are several pre-defined contentHandlers available to use. The value represents the key in the handlers map.
text (default) - Simply returns the response text
json - Converts response text into a JSON object
xml - Returns a XML document
javascript - Evaluates the response text
json-comment-filtered - A (arguably unsafe) handler to preventing JavaScript hijacking
json-comment-optional - A handler which detects the presence of a filtered response and toggles between json or json-comment-filtered appropriately.
Examples

Dom string doesn't change after manipulation with jQuery attr

I'm making a js-based epub reader as a weekend project and I'm trying to change the src attribute of the images on each of the book's pages from image urls to data URI's loaded from the epub zip. Here's my function:
//page contents is just an html string of the book's page
pageContents = GlobalZipLoader.load('epub.zip://' + pageLocation);
pageContents = replaceImages(pageContents)
...
function replaceImages(pageContents){
$(pageContents).find('img').each(function(){
var domImage = $(this);
//this is something like ".../Images/img.jpg"
var imageLocation = domImage.attr('src');
//this returns the proper data-uri representation of the image
var dataUri = GlobalZipLoader.loadImage('epub.zip://' + imageLocation);
//this doesn't seem to "stick"
domImage.attr('src', dataUri);
});
return pageContents;
}
The returned pageContents from the replaceImages functions still has the old src attributes. I can provide more detail if needed but any help would be very much appreciated.
Correct answer thanks to The System Restart and Ilia G:
function replaceImages(pageContents) {
newContent = $(pageContent);
... manip ...
return newContent;
}
You don't need to clone it. Simply set pageContents = $(pageContents);, then perform your image replacement on pageContents, then return pageContents.html();
you should try to change the image src after image load complete;
and I think this is happening with in loadImage function.
According to your update question:
You don't need any clone(), I think. Just store pageContents in a tempContents variable and use that variable
Since pageContents is just a string, you'll need to return the modified version of it. Try this:
function replaceImages(pageContents){
// save jQuery object
var $pageContents = $(pageContents);
$pageContents.find('img').each(function(){
var domImage = $(this);
//this is something like ".../Images/img.jpg"
var imageLocation = domImage.attr('src');
//this returns the proper data-uri representation of the image
var dataUri = GlobalZipLoader.loadImage('epub.zip://' + imageLocation);
//this doesn't seem to "stick"
domImage.attr('src', dataUri);
});
// return contents of the modified jQuery object
return $pageContents.html();
}

Categories