How to include external JavaScript library in reactjs - javascript

I would like to know how it's possible to include an external JavaScript library in a react project. For example, I would like to import the jspdf library : https://github.com/MrRio/jsPDF/blob/master/jspdf.js and use it in my reactjs app.
So far I tried to use require like this : 
let React = require('react');
let { Spacing, Typography } = Styles;
let DoughnutChart = require("react-chartjs").Doughnut;
let Chart = require('react-google-charts').Chart;
let { StylePropable, StyleResizable } = Mixins;
let EditableDiv = require('../EditableDiv.jsx');
//some other library
//the library that matter for me
var pdfConverter = require('../utils/jspdf.source.js');
//then I have my classical react code which works and a function to generate ad pdf
_generatePdf: function(){
console.log('Genrating pdf');
var doc = new pdfConverter.jsPDF('p','pt');
var img = new Image();
}
I have the following error : TypeError: pdfConverter.jsPDF is not a function.
To make it work, I made something ugly, I copy the source of jspdf-source.js into my react.jsx file and just call jsPDF instead of pdfConverter.jsPDF. It's definitely no the right way, but can't succeed to import and use the library.
Can you tell me what I'm doing wrong and how I can correct this?
-EDIT-
When I was using my ugly solution (copying the source into my file) I just had to do the following :
var doc = new jsPDF('p','pt);
And it was working perfectly, expect that I had a very big file
After the suggested solution from #dannyjolie bellow, I've imported jspdf directly from the npm package, but I'm still not able to use the library. I tried the following code which lead to an error:
var pdfConverter = require('jspdf');
var converter = new pdfConverter();
var doc = converter.jsPDF('p', 'pt');
TypeError: pdfConverter is not a constructor
Meaning that I have to import the jsPDF coming from the package, not only jspdf?
Then I tried
let pdfConverter = require('jspdf');
var converter = pdfConverter.jsPDF;
var doc = new converter('p', 'pt');
ReferenceError: jsPDF is not defined
TypeError: converter is not a constructor
Ok, obviously, I'm not importing the right thing or not the right way.
What I'm doing wrong?

If you include the external js file link in your /public/index.html, you can use the external library with the window prefix.
Take JQuery as an example. Put the following line in your /public/index.html:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
Use it in your project like so:
window.$("#btn1").click(function(){
alert("Text: " + $("#test").text());
});

First of all, don't use the source file. Just npm install jspdf --save like any other package, and import it with var pdfConverter = require('jspdf');
Secondly, you're missing a () in this line var doc = new pdfConverter.jsPDF('p','pt');
Do something like this:
var converter = new pdfConverter();
var doc = converter.jsPDF('p', 'pt');

I know this is old, but I thought it would be helpful if someone posted a full working sample. It took me a while to figure this out, using this other post as a starting point:
How to make PDF from React?
Assuming you are using create-react-app, overwrite your App.js with the following below...
import React, { Component } from 'react';
import pdfConverter from 'jspdf';
import logo from './logo.svg';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
this.toDataUrl = this.toDataUrl.bind(this);
}
toDataUrl(url, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
var reader = new FileReader();
reader.onloadend = function() {
callback(reader.result);
}
reader.readAsDataURL(xhr.response);
};
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.send();
}
onClick() {
var doc = new pdfConverter('p','pt','letter');
//console.log(doc.getFontList() );
this.toDataUrl('background.jpg', function(base64Img) {
var imgData = base64Img;
console.log(imgData);
console.log('Adding to doc.');
doc.addImage(imgData, 'JPEG', 0, 0, 612, 792);
console.log('Image added.');
doc.setFont('Times', 'Roman');
doc.setFontSize(22);
doc.text(20, 50, 'Park Entry Ticket');
doc.setFontSize(16);
doc.text(20, 80, 'Address1: ' );
doc.text(20, 100, 'Address2: ' );
doc.text(20, 120, 'Entry Date & time: ');
doc.text(20, 140, 'Expiry date & time: ' );
console.log('About to save');
doc.save("test.pdf");
});
}
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
<input type='button'
onClick={this.onClick} value="Print"/>
</p>
</div>
);
}
}
export default App;

Related

How can I "fake" a url to an html page from an html string?

On my React website, I'd like to generate an image from an html string.
I've found html-to-image which seems stable and popular, but it requires a URL to the page of which I want to take a screenshot of.
How can I generate a "fake" URL to give it?
The HTML string I have is basically a design of the image I want but the content depends on user input.
EDIT: (added the HTML string)
This is my HTML string:
<!DOCTYPE html> <html> <body> <div style="width:500px;margin:0px;padding:0px;background-color:white' \
';"><div> <div style="padding:50px"> <p ' \
'style="color:#9F9F9F;font-size:13px;font-family:verdana;margin-top:0px">VARIABLEVARIABLE</p> <p ' \
'style="color:#3F3F3F;font-size:26px;font-weight:900;margin-top:0px;margin-bottom:18px;font-family' \
':verdana">VARIABLEVARIABLE</p> <p style="color:#3F3F3F;font-size:15px;font-weight:500;margin-top:0px;font-family' \
':verdana">VARIABLEVARIABLE</p> </div> <div style="width:100%;height:10px;background-color:#EFF5F8;"></div><div ' \
'style="padding:50px"> <p style="color:#9F9F9F;font-size:13px;font-family:verdana">VARIABLEVARIABLE</p> <p ' \
'style="color:#3F3F3F;font-size:15px;font-weight:500;margin-top:0px;font-family:verdana">VARIABLEVARIABLE</p> ' \
'</div></div> <div style="width:100%;height:55px;background-color:#313131;margin-right:0px;margin-left' \
':0px;line-height:55px;"> <p style="color:#ffffff;font-size:15px;font-weight:500;font-family:verdana' \
';margin-left:50px">VARIABLEVARIABLE</p> </div> </div> </body> </html>
So I get data fom the server, then replace where I wrote VARIABLEVARIABLE with some of the data and I want to present it to the user as an image.
EDIT 2 :
Reading the comment from #programoholic I think that he's right and I got it wrong. I kept seeing dataUrl but I understand now that it's not an actual URL that needs to be passed, but just a reference to the node in which the HTML exists.
I'm still unsure how to approach this, but it does change the question.
I'll try to set the html to the node once I get the data and then take a snap of that, maybe that'll work.
html-to-string doesn't require any url. Instead you can use the useRef to select the node and then generate the html content as an image like below :
import React, { useRef, useCallback } from 'react';
import './style.css';
import { toPng } from 'html-to-image';
export default function App() {
const ref = useRef();
const onButtonClick = useCallback(() => {
if (ref.current === null) {
return;
}
toPng(ref.current, { cacheBust: true })
.then((dataUrl) => {
const link = document.createElement('a');
link.download = 'my-image-name.png';
link.href = dataUrl;
link.click();
})
.catch((err) => {
console.log(err);
});
}, [ref]);
return (
<div ref={ref}>
<h1>Hello StackBlitz!</h1>
<p>Start editing to see some magic happen :) p</p>
<button onClick={onButtonClick}> download png </button>
</div>
);
}
Here is the. : Stackblitz
html-to-image wants base64 url , so you can create image to base64 with javascript code.
const base64Convertor = (file) => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onload = () => {
resolve(fileReader.result);
};
fileReader.onerror = (error) => {
reject(error);
};
});
};
You can add some JavaScript to replace the contents of some HTML elements with the value of your variable, which can be taken from a URL parameter.
Then pass the URL with the value in the parameter.
Eg: /generate-image.html?variable=Hello
// Get variable from URL query params
const urlSearchParams = new URLSearchParams(window.location.search);
const variable = urlSearchParams.get('variable') || 'default value';
// Update all HTML elements with data-variable
const elements = document.querySelectorAll('[data-variable]');
for (element of elements) {
element.textContent = variable;
}
<h1 data-variable="true"></h1>
<p data-variable="true"></p>

Extracting source attribute of generated img by qrcode.js

Like I said in the title, my problem is that I get an empty string back.
I'm jusing qrcode.js from https://github.com/davidshimjs/qrcodejs .
My Code:
<script src="qrcode.js"></script>
<div id="qr"></div>
<img id="test" src="https://www.google.de/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png">
<script type="text/javascript">
var qrCode = new QRCode(
document.getElementById('qr'),
{
text: 'www.google.de',
width: 150,
height: 150,
onSuccess: (value) => {
console.log('value',value);
}
}
);
</script>
<script>
var test = document.getElementById("test").src;
console.log(test);
var base64 = document.getElementById("qr_neu").src;
console.log(base64);
console.log(typeof base64);
console.log(base64.length);
var dom = document.getElementById("qr_neu").attributes;
console.log(dom);
var code = dom[3];
console.log(code);
</script>
The generated QR-Code works fine and in the developer settings in chrome i can see the src of both
Screenshot:
console in chrome
Now I don't understand wha I can't access to the src attribute of the qr-code but on the google img.
I also tried the callbackversion descriped on the github issues section but it doesn't work either.
All i want is the base64 code as var for ther applications.
Thanks for helping!
The reason why you get an empty string back, even though you can see the src value in your dev tools, is that it takes a very short amount of time to generate the QR-Code.
So var base64 = document.getElementById("qr_neu").src;is called before the QR-Code is generated.
Here is a relevant issues on the qrcode.js repository: https://github.com/davidshimjs/qrcodejs/issues/160.
Here is the solution adapted to your code:
const qrDiv = document.getElementById('qr')
var qrCode = new QRCode(
qrDiv,
{
text: 'www.google.de',
width: 150,
height: 150,
onSuccess: (value) => {
console.log('value',value);
}
}
);
const src = qrDiv.children[0].toDataURL("image/png");
console.info(src);

How to modify Backbone JS function in Odoo 8?

I want to modify a section of JS code in Odoo 8 (module point_of_sale). The original code is this one:
function openerp_pos_models(instance, module){
...
module.Order = Backbone.Model.extend({
...
addPaymentline: function(cashregister) {
var paymentLines = this.get('paymentLines');
var newPaymentline = new module.Paymentline({},{cashregister:cashregister, pos:this.pos});
if(cashregister.journal.type !== 'cash'){
newPaymentline.set_amount( Math.max(this.getDueLeft(),0) );
}
paymentLines.add(newPaymentline);
this.selectPaymentline(newPaymentline);
},
});
}
I modified some lines of that code and the changes are working as I want (I only removed the if (cashregister.journal.type !== 'cash') line). The problem is that now, I want to modify this code on a right way, from a module made by me.
To do that, I added a JavaScript file, which is called from the following XML file (this last one is included in my __openerp__.py data parameter):
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="assets_backend" name="nmx_pos_ext assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/nmx_pos_ext/static/src/js/nmx_pos_ext.js"></script>
</xpath>
</template>
</data>
</openerp>
And the content of the JS file is:
openerp.nmx_pos_ext = function(instance) {
var _t = instance.web._t;
instance.point_of_sale.Order.include({
addPaymentline: function(cashregister) {
var paymentLines = this.get('paymentLines');
var newPaymentline = new module.Paymentline({},{cashregister:cashregister, pos:this.pos});
newPaymentline.set_amount( Math.max(this.getDueLeft(),0) );
paymentLines.add(newPaymentline);
this.selectPaymentline(newPaymentline);
},
});
}
I updated the module and the changes are not being applied, I get an error because include seems to not exist in Backbone models. I tried with set instead of include, but I get the same error:
instance.point_of_sale.Order.set is not a function
Can anyone help me here, please?
You can try like this way.
openerp.nmx_pos_ext = function(instance) {
var _t = instance.web._t;
var _initialize_Order_ = instance.point_of_sale.Order.prototype;
instance.point_of_sale.Order = instance.point_of_sale.Order.extend({
initialize: function(attributes){
_initialize_Order_.initialize.call(this,attributes);
},
addPaymentline: function(cashregister) {
var paymentLines = this.get('paymentLines');
var newPaymentline = new instance.point_of_sale.Paymentline(
{},
{
cashregister: cashregister,
pos: this.pos
}
);
newPaymentline.set_amount(
Math.max(this.getDueLeft(), 0)
);
paymentLines.add(newPaymentline);
this.selectPaymentline(newPaymentline);
},
});
}
Try this:
instance.module.Order.include({
addPaymentline: function(cashregister) {
var paymentLines = this.get('paymentLines');
var newPaymentline = new module.Paymentline({},{cashregister:cashregister, pos:this.pos});
newPaymentline.set_amount( Math.max(this.getDueLeft(),0) );
paymentLines.add(newPaymentline);
this.selectPaymentline(newPaymentline);
},
});

Meteor froala:editor-reactive save on change of data

I have Meteor project which uses the froala:editor-reactive package in order to set the user's about me field.
Here is my template js code:
Template.profile.helpers({
getAbout: function() {
return Meteor.user().profile.about;
},
doSave: function (e, editor) {
// Get edited HTML from Froala-Editor
var newHTML = editor.getHTML();
// Do something to update the edited value provided by the Froala-Editor plugin, if it has changed:
if (!_.isEqual(newHTML, Meteor.user().profile.about)) {
Meteor.call("updateTestimony", Meteor.userId(), newHTML);
}
return false; // Stop Froala Editor from POSTing to the Save URL
}
}
Here is my template html code:
<template name="profile">
<div>
{{> froalaReactive _onbeforeSave=doSave _value=getAbout}}
</div>
</template>
It's supposed to save as the value changes (I hope).
But I have an error with the line var newHTML = editor.getHTML(); and I've also tried var newHTML = editor.html.get(true);. Both of these result in an error where it cannot read the property of html or getHTML. I'm hoping this is just a syntax error and I need something else but what's wrong here?
Per the plugin docs, try:
var newHTML = editor.html.get(true /* keep_markers */);
If that doesn't work, you may possibly be using a different version. In which case, give the following syntaxes a shot:
var newHTML = $('.your_selector').editable('getHTML', true, true);
var newHTML = $('.your_selector').froalaEditor('html.get', true);
More from the official docs here and see this question.

Print static SWF on HTML

I've been trying really hard on this with no results, hope someone could help me out.
What I have is an HTML page with a ActionScript2 SWF object embedded. The SWF is a static sprite that gets dynamic text from the javascript. So basically looks like an image.
I want to print out the whole page HTML + SWF included, but as expected on the possition of the SWF object appears a blank square.
I print the page using javascript window.print();
Is there anyway to take a snapshot of the SWF or render it like an image? to show it on the print preview and on the printed document?
The size of the flash object is 600x381px;
Thank you!
Sorry guys、but I finally came up with a solution.
Thanks for having a look anyways.
What I first did is to convert the flash file from ActionScript2 to ActionScript3 to be able to use the as3corelib of Mike Chambers https://github.com/mikechambers/as3corelib.
From this library I used the JGPEncoder as seen below
import flash.external.ExternalInterface;
import flash.display.JPEGEncoderOptions;
import com.adobe.images.JPGEncoder;
import flash.display.BitmapData;
import flash.utils.ByteArray;
import flash.display.Bitmap;
import flash.net.URLRequest;
import flash.net.URLLoader;
import flash.events.Event;
function snapShot(){
var imgBM:Bitmap;
var myBitmapData:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight);
myBitmapData.draw(stage);
imgBM=new Bitmap(myBitmapData);
addChild(imgBM);
var imgBA:ByteArray;
var jpgEncoder:JPGEncoder = new JPGEncoder(90);
//-------Send image to php
imgBA = jpgEncoder.encode(myBitmapData);
var sendHeader:URLRequestHeader = new URLRequestHeader('Content-type', 'application/octet-stream');
var sendReq:URLRequest = new URLRequest("parseimg.php");
sendReq.requestHeaders.push(sendHeader);
sendReq.method = URLRequestMethod.POST;
sendReq.data = imgBA;
var sendLoader:URLLoader = new URLLoader;
sendLoader.addEventListener(Event.COMPLETE, imageSentHandler);
sendLoader.load(sendReq);
}
var imagePath:String;
function imageSentHandler(event:Event):void {
var dataStr:String = event.currentTarget.data.toString();
var resultVars:URLVariables = new URLVariables();
resultVars.decode(dataStr);
imagePath = "http://" + resultVars.base + resultVars.filename;
}
The next step was to create the php that receives the ByteArray and creates the image file on the server.
<?php
if ( isset ( $GLOBALS["HTTP_RAW_POST_DATA"] )) {
$filename = "your_image_name.jpg";
$fp = fopen( $filename,"wb");
fwrite( $fp, $GLOBALS[ 'HTTP_RAW_POST_DATA' ] );
fclose( $fp );
echo "filename=".$filename."&base=".$_SERVER["HTTP_HOST"].dirname($_SERVER["PHP_SELF"]); } ?>
Finally and with the image already in a folder on the server, I just had to hide the Embedded flash object using CSS, and show up the image instead.
I got this using jquery on document.ready
var d = new Date();
setTimeout(function(){
$("#imgflash").attr("src", "your_image_name.jpg?"+d.getTime());
setTimeout("window.print();", 200);
},1000);
As I'm pretty new on ActionScript and Flash, any improvements on this code are kindly accepted.

Categories