first commit

This commit is contained in:
2024-04-19 14:04:41 +07:00
commit 014283036f
7282 changed files with 1324127 additions and 0 deletions
+281
View File
@@ -0,0 +1,281 @@
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
JSPM_WS_Status: null,
DemoIndex: 0
};
this.setDemoSample = this.setDemoSample.bind(this);
}
jspmWsStatusChanged(status) {
this.setState({
JSPM_WS_Status: status
});
}
setDemoSample(index) {
this.setState({
DemoIndex: index
});
}
componentDidMount() {
JSPM.JSPrintManager.auto_reconnect = true;
JSPM.JSPrintManager.start();
JSPM.JSPrintManager.MainApp = this;
JSPM.JSPrintManager.WS.onOpen = function() {
JSPM.JSPrintManager.MainApp.jspmWsStatusChanged(
JSPM.WSStatus[JSPM.JSPrintManager.WS.status]
);
};
JSPM.JSPrintManager.WS.onStatusChanged = function() {
JSPM.JSPrintManager.MainApp.jspmWsStatusChanged(
JSPM.WSStatus[JSPM.JSPrintManager.WS.status]
);
};
JSPM.JSPrintManager.WS.onClose = function() {
JSPM.JSPrintManager.MainApp.jspmWsStatusChanged(
JSPM.WSStatus[JSPM.JSPrintManager.WS.status]
);
};
}
render() {
let year = new Date().getFullYear();
let demoContent;
if (this.state.JSPM_WS_Status == "Open") {
if (this.state.DemoIndex == 0) {
demoContent = <DemoStartPage setSample={this.setDemoSample} />;
} else if (this.state.DemoIndex == 1) {
demoContent = (
<PrintingRawCommandsSample setSample={this.setDemoSample} />
);
} else if (this.state.DemoIndex == 2) {
demoContent = (
<PrintingPDFSample setSample={this.setDemoSample} />
);
} else if (this.state.DemoIndex == 3) {
demoContent = (
<PrintingFilesSample setSample={this.setDemoSample} />
);
} else if (this.state.DemoIndex == 4) {
demoContent = (
<PrintingMultiplePrintJobsSample
setSample={this.setDemoSample}
/>
);
} else if (this.state.DemoIndex == 5) {
demoContent = (
<PrintingTXTSample setSample={this.setDemoSample} />
);
} else if (this.state.DemoIndex == 6) {
demoContent = (
<PrintersInfoSample setSample={this.setDemoSample} />
);
}
} else if (this.state.JSPM_WS_Status == "Closed")
demoContent = <InstallJSPMClientApp />;
else if (this.state.JSPM_WS_Status == "BlackListed")
demoContent = <WebsiteBlackListed />;
else {
demoContent = (
<div className="row">
<div className="col-md-12">
<div className="text-center">
<img src="loading.gif" id="loadingPrintersInfo" />
<br />
<strong>Waiting for user response....</strong>
</div>
</div>
</div>
);
}
return (
<div>
<nav className="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
<div className="container">
<a
className="navbar-brand"
href="//neodynamic.com/products/printing/js-print-manager"
target="_blank"
>
<img
alt="Neodynamic"
src="//neodynamic.com/images/jspm-32.png"
/>
&nbsp;&nbsp;JSPrintManager{" "}
<span className="round">2.0</span>
</a>
<button
className="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbarsExampleDefault"
aria-controls="navbarsExampleDefault"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span className="navbar-toggler-icon" />
</button>
<div
className="collapse navbar-collapse"
id="navbarsExampleDefault"
>
<div className="mr-auto" />
<a
href="https://github.com/neodynamic/JSPrintManager/"
target="_blank"
title="Download Source Code..."
className="githubIcon"
>
<i className="fa fa-github" />
</a>
<JSPMStatus JSPM_WS_Status={this.state.JSPM_WS_Status} />
</div>
</div>
</nav>
<div className="container content">
<h2>
JSPrintManager{" "}
<small>
<em>
Print RAW Commands &amp; Known File Formats from
Javascript
</em>
</small>
</h2>
<hr />
{demoContent}
<footer>
<br />
<br />
<br />
<br />
<hr />
<p>
<a
href="//neodynamic.com/products/printing/js-print-manager/"
target="_blank"
>
JSPrintManager for any Web Platform!
</a>
&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;
<i className="icon-user" />{" "}
<a href="//neodynamic.com/support" target="_blank">
Contact Tech Support
</a>
</p>
<p>
Copyright &copy; 2003-{year}
<br />
Neodynamic SRL
<br />
<a
href="//neodynamic.com"
alt="Neodynamic Website"
target="_blank"
>
https://neodynamic.com
</a>
</p>
</footer>
</div>
<div
id="files-requirements-dialog"
className="modal fade topMost"
tabIndex="-1"
role="dialog"
aria-labelledby="exampleModalLabel"
aria-hidden="true"
>
<div className="modal-dialog modal-lg" role="document">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title" id="exampleModalLabel">
Client System Requeriments
</h5>
<button
type="button"
className="close"
data-dismiss="modal"
aria-label="Close"
>
<span aria-hidden="true">&times;</span>
</button>
</div>
<div className="modal-body">
<table className="table table-bordered">
<thead>
<tr className="fileFormats">
<td>File Format</td>
<td>Windows Clients</td>
<td>UNIX Clients</td>
</tr>
</thead>
<tbody>
<tr>
<td>DOC, DOCX</td>
<td>Microsoft Word is required</td>
<td>LibreOffice is required</td>
</tr>
<tr>
<td>XLS, XLSX</td>
<td>Microsoft Excel is required</td>
<td>LibreOffice is required</td>
</tr>
<tr>
<td>PDF</td>
<td>Natively supported!</td>
<td>Natively supported!</td>
</tr>
<tr>
<td>TXT</td>
<td>Natively supported!</td>
<td>Natively supported!</td>
</tr>
<tr>
<td>JPEG</td>
<td>Natively supported!</td>
<td>Natively supported!</td>
</tr>
<tr>
<td>PNG</td>
<td>Natively supported!</td>
<td>Natively supported!</td>
</tr>
<tr>
<td>BMP</td>
<td>Natively supported!</td>
<td>Natively supported!</td>
</tr>
</tbody>
</table>
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-secondary"
data-dismiss="modal"
>
Close
</button>
</div>
</div>
</div>
</div>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
window.App = App;
@@ -0,0 +1,173 @@
class DemoStartPage extends React.Component {
render() {
return (
<div>
<h1 className="text-center">Available Demos</h1>
<hr />
<div className="row">
<div className="col-sm-6">
<h2>
<i className="fa fa-barcode" />&nbsp;Raw Data Printing
</h2>
<p>
Send any raw data &amp; commands supported by the client
printer like{" "}
<strong>
Epson ESC/POS, HP PCL, PostScript, Zebra ZPL and Eltron
EPL, and more!
</strong>
</p>
<button
className="btn btn-lg btn-info"
onClick={() => this.props.setSample(1)}
>
Try it now...
</button>
</div>
<div className="col-sm-6">
<h2>
<i className="fa fa-file-pdf-o" />&nbsp;Advanced PDF
Printing
</h2>
<p>
Print <strong>PDF</strong> files{" "}
<strong>
without requiring Adobe Reader or any other external
software!
</strong>{" "}
Advanced PDF Printing settings include{" "}
<strong>Tray Name</strong>, <strong>Paper Size</strong>,{" "}
<strong>Print Rotation</strong>,{" "}
<strong>Pages Range</strong>, and more!
</p>
<button
className="btn btn-lg btn-info"
onClick={() => this.props.setSample(2)}
>
Try it now...
</button>
</div>
</div>
<br />
<div className="row">
<div className="col-sm-6">
<h2>
<i className="fa fa-file-image-o" />&nbsp;Print Images &amp;
Docs
</h2>
<p>
In addition to print raw commands, you can also print known
file formats like{" "}
<strong>PDF, TXT, DOC/x, XLS/x, JPG, PNG, and more!</strong>{" "}
PDF, TXT, PNG, JPG and BMP are natively supported; others
will require external software like Word, Excel,
LibreOffice, etc.
</p>
<button
className="btn btn-lg btn-info"
onClick={() => this.props.setSample(3)}
>
Try it now...
</button>
</div>
<div className="col-sm-6">
<h2>
<i className="fa fa-barcode" />+
<i className="fa fa-file-text" />&nbsp;Print Multiple Jobs
in one shot!
</h2>
<p>
<strong>
Print multiple jobs to the same or different printers in
one shot!
</strong>{" "}
You can mix Raw commands and Known File Formats!
</p>
<button
className="btn btn-lg btn-info"
onClick={() => this.props.setSample(4)}
>
Try it now...
</button>
</div>
</div>
<br />
<div className="row">
<div className="col-sm-6">
<h2>
<i className="fa fa-file-text-o" />&nbsp;Advanced TXT
Printing
</h2>
<p>
Print <strong>TXT</strong> files or{" "}
<strong>just plain text</strong> including settings like{" "}
<strong>Font (name, size, style)</strong>,{" "}
<strong>Text Color</strong>,{" "}
<strong>
Text Alignments (left, center, right, justify)
</strong>
, <strong>Print Orientation</strong>, and more!
</p>
<button
className="btn btn-lg btn-info"
onClick={() => this.props.setSample(5)}
>
Try it now...
</button>
</div>
<div className="col-sm-6">
<h2>
<i className="fa fa-print" />&nbsp;Get Printers Info
</h2>
<p>
Get the <strong>list of installed printers</strong>{" "}
available in the client machine including details like{" "}
<strong>
DPI Resolution, PortName, "Is Connected", "Is Shared", "Is
Local", "Is Network"
</strong>
, as well as the{" "}
<strong>
list of supported Papers and list of trays/bins!
</strong>
</p>
<button
className="btn btn-lg btn-info"
onClick={() => this.props.setSample(6)}
>
Try it now...
</button>
</div>
</div>
<hr />
<div className="row">
<div className="col-sm-12">
<h2>
<i className="fa fa-mixcloud" />&nbsp;Print from Mobile
&amp; Sandboxed Devices
</h2>
<p>
Printing from clients such as{" "}
<strong>
mobile/sandboxed devices (running iOS, Android,
ChromeOS...)
</strong>{" "}
and <strong>Terminal Services/Citrix environments</strong>{" "}
is possible with{" "}
<strong>JSPrintManager in Print Server Mode</strong>,
</p>
<a
className="btn btn-lg btn-info"
href="https://www.neodynamic.com/articles/How-to-print-raw-commands-pdf-files-from-iOS-Android-ChromeOS-sandboxed-devices-from-Javascript"
target="_blank"
>
Learn how to do it...
</a>
</div>
</div>
</div>
);
}
}
window.DemoStartPage = DemoStartPage;
@@ -0,0 +1,42 @@
class InstallJSPMClientApp extends React.Component {
render() {
return (
<div>
<h2>Download &amp; Install JSPM Client App</h2>
<hr />
It seems that{" "}
<strong>
JSPM Client App is not installed or not running
</strong>{" "}
in this machine!
<br />
<br />
<strong>JSPM Client App</strong> is a small utility (
<strong>
<em>without any dependencies</em>
</strong>
) that handles all the <strong>Print Jobs</strong> and runs on{" "}
<strong>Windows, Linux, Mac &amp; Raspberry Pi</strong> devices!
<br />
<br />
<div className="text-center">
<a
href="//neodynamic.com/downloads/jspm"
target="_blank"
className="btn btn-lg btn-primary center"
>
<i className="fa fa-download" /> Download JSPM Client App...
</a>
</div>
<br />
<div className="alert alert-warning">
<i className="fa fa-exclamation-circle" /> Browser needs to be
restarted after package installation! Firefox-based browser must
be closed (all open instances) before installing JSPM utility.
</div>
</div>
);
}
}
window.InstallJSPMClientApp = InstallJSPMClientApp;
@@ -0,0 +1,38 @@
class JSPMStatus extends React.Component {
render() {
let jspm_status;
if (this.props.JSPM_WS_Status == "Open")
jspm_status = (
<span className="badge badge-success">
<i className="fa fa-check" /> Open
</span>
);
else if (this.props.JSPM_WS_Status == "Closed")
jspm_status = (
<span className="badge badge-danger">
<i className="fa fa-exclamation-circle" /> Closed!
</span>
);
else if (this.props.JSPM_WS_Status == "BlackListed")
jspm_status = (
<span className="badge badge-warning">
<i className="fa fa-times-circle" /> This Website is Black
Listed!
</span>
);
else
jspm_status = (
<span className="badge badge-warning">
<i className="fa fa-user-circle" /> Waiting for user response...
</span>
);
return (
<span className="jspmStatus">
<strong>JSPM</strong> WebSocket Status {jspm_status}
</span>
);
}
}
window.JSPMStatus = JSPMStatus;
@@ -0,0 +1,164 @@
class PrintJob extends React.Component {
constructor(props) {
super(props);
this.state = {
printJobType: 0,
clientPrinter: null,
printerCommands: "",
printFiles: []
};
}
setPrintJobType(event) {
this.setState({ printJobType: event.target.value });
}
deleteJob() {
this.props.removeJobHandler(this.props.jobIndex);
}
updateJob() {
var cpj = new JSPM.ClientPrintJob();
cpj.clientPrinter = this.state.clientPrinter;
cpj.printerCommands = this.state.printerCommands;
if (this.state.printFiles) {
let files = this.state.printFiles;
for (let j = 0; j < files.length; j++) {
let my_file;
if (files[j].name)
my_file = new JSPM.PrintFile(
files[j],
JSPM.FileSourceType.BLOB,
files[j].name,
1
);
else
my_file = new JSPM.PrintFile(
files[j],
JSPM.FileSourceType.URL,
"myFileToPrint." + files[j].split(".").pop(),
1
);
cpj.files.push(my_file);
}
}
this.props.updateJobHandler(this.props.jobIndex, cpj);
}
onPrinterChange(newPrinter) {
//No need to re-render!
this.state.clientPrinter = newPrinter;
this.updateJob();
}
onPrinterCommandsChange(newPrinterCommands) {
//No need to re-render!
this.state.printerCommands = newPrinterCommands;
this.updateJob();
}
onPrintFilesChange(newFiles) {
//No need to re-render!
this.state.printFiles = newFiles;
this.updateJob();
}
render() {
let jobIndex = "collapse-" + this.props.jobIndex;
let jobIndexDT = "#" + jobIndex;
let jobType = (
<PrintJobForRawCommands
jobIndex={this.props.jobIndex}
onPrinterCommandsChange={this.onPrinterCommandsChange.bind(this)}
/>
);
if (this.state.printJobType == 1) {
jobType = (
<PrintJobForFiles
jobIndex={this.props.jobIndex}
onPrintFilesChange={this.onPrintFilesChange.bind(this)}
/>
);
}
return (
<div>
<div className="card">
<div className="card-header">
<div className="input-group">
<div
className="input-group-prepend"
data-toggle="collapse"
data-target={jobIndexDT}
aria-expanded="true"
aria-controls={jobIndex}
>
<label
className="input-group-text"
htmlFor="selectcontentType"
data-toggle="tooltip"
data-placement="left"
title="Expand/Collapse"
>
<i className="fa fa-list-alt" />&nbsp;Print Job Content
Type:
</label>
</div>
<select
className="custom-select"
aria-describedby="selectcontentType"
onChange={this.setPrintJobType.bind(this)}
>
<option value="0">RAW Printer Commands</option>
<option value="1">
Files (PDF, TXT, PNG, JPG, etc.)
</option>
</select>
<div className="input-group-append">
<button
className="btn btn-danger"
type="button"
onClick={this.deleteJob.bind(this)}
>
<i className="fa fa-minus white" />
</button>
</div>
<div className="input-group-append">
<button
className="btn btn-dark"
type="button"
data-toggle="collapse"
data-target={jobIndexDT}
aria-expanded="true"
aria-controls={jobIndex}
>
<i className="fa fa-chevron-down white" />
</button>
</div>
</div>
</div>
<div
id={jobIndex}
className="collapse show"
data-parent="#accordion"
>
<div className="card-body">
<div className="row">
<Printers
JobContentType={this.state.printJobType}
onPrinterChange={this.onPrinterChange.bind(this)}
/>
</div>
<div className="row">{jobType}</div>
</div>
</div>
</div>
<br />
</div>
);
}
}
window.PrintJob = PrintJob;
@@ -0,0 +1,107 @@
class PrintJobForFiles extends React.Component {
constructor(props) {
super(props);
this.state = {
printFiles: null
};
}
setPrintFiles(event) {
//no need to re-render
if (event.target.name == "input-local-files")
this.state.printFiles = Array.from(event.target.files);
else this.state.printFiles = [event.target.value];
this.props.onPrintFilesChange(this.state.printFiles);
}
render() {
return (
<div className="col-md-12">
<hr />
<strong>Select the File(s) to print</strong>
<div className="alert alert-warning">
<small>
Remember to check if you meet the requeriments before printing
files!&nbsp;
<a
data-toggle="modal"
data-target="#files-requirements-dialog"
href=""
>
<strong>Check them here...</strong>
</a>
</small>
</div>
<ul
className="nav nav-tabs"
id={"myTab-" + this.props.jobIndex}
role="tablist"
>
<li className="nav-item">
<a
className="nav-link active"
id={"local-files-tab-" + this.props.jobIndex}
data-toggle="tab"
href={"#local-files-" + this.props.jobIndex}
role="tab"
aria-controls={"local-files-" + this.props.jobIndex}
aria-selected="true"
>
Local Files
</a>
</li>
<li className="nav-item">
<a
className="nav-link"
id={"remote-file-tab-" + this.props.jobIndex}
data-toggle="tab"
href={"#remote-file-" + this.props.jobIndex}
role="tab"
aria-controls={"remote-file-" + this.props.jobIndex}
aria-selected="false"
>
File from URL
</a>
</li>
</ul>
<div
className="tab-content"
id={"myTabContent-" + this.props.jobIndex}
>
<div
className="tab-pane fade show active"
id={"local-files-" + this.props.jobIndex}
role="tabpanel"
aria-labelledby={"local-files-tab-" + this.props.jobIndex}
>
<br />
<input
name="input-local-files"
type="file"
multiple="multiple"
className="form-control-file"
onChange={this.setPrintFiles.bind(this)}
/>
</div>
<div
className="tab-pane fade"
id={"remote-file-" + this.props.jobIndex}
role="tabpanel"
aria-labelledby={"remote-file-tab-" + this.props.jobIndex}
>
<br />
URL File <strong>must include file extension!</strong>
<input
name="input-file-url"
className="form-control form-control-sm"
onChange={this.setPrintFiles.bind(this)}
/>
</div>
</div>
</div>
);
}
}
window.PrintJobForFiles = PrintJobForFiles;
@@ -0,0 +1,77 @@
class PrintJobForRawCommands extends React.Component {
constructor(props) {
super(props);
this.state = {
printerCommands: ""
};
}
setPrinterCommands(cmds) {
//console.log(cmds);
//no need to re-render
this.state.printerCommands = cmds;
this.props.onPrinterCommandsChange(this.state.printerCommands);
}
setPredefinedCommands(cmdId){
let cmds = '';
if(cmdId == 'zpl')
cmds = '^XA^FO30,40^ADN,36,20^FDZPL Printed from JSPrintManager^FS^FO30,60^BY4^B3N,,200^FD12345678^FS^XZ';
else if(cmdId == 'epl')
cmds = '\x0AN\x0AQ609,24\x0Aq784\x0AA170,5,0,1,5,5,N,"EPL Printed from JSPrintManager"\x0AB170,50,0,3C,2,6,120,B,"BCP-1234"\x0AP1\x0A';
else if(cmdId == 'escpos')
cmds = '\x1b@\x1bE\x01ESC POS Printed from JSPrintManager\x1bd\x01\x1dk\x04987654321\x00\x1bd\x01987654321\x1dV\x41\x03';
else if(cmdId == 'ipl')
cmds = '<STX><ESC>C<ETX><STX><ESC>P<ETX><STX>E4;F4<ETX><STX>H0;o200,100;f0;c25;h20;w20;d0,30<ETX><STX>L1;o200,150;f0;l575;w5<ETX><STX>B2;o200,200;c0,0;h100;w2;i1;d0,10<ETX><STX>I2;h1;w1;c20<ETX><STX>R<ETX><STX><ESC>E4<ETX><STX><CAN><ETX><STX>IPL Printed from JSPrintManager<CR><ETX><STX>SAMPLE<ETX><STX><ETB><ETX>';
else if(cmdId == 'dpl')
cmds = '\x02L\x0dH07\x0dD11\x0d191100801000025DPL Printed from JSPrintManager\x0d1a6210000000050590PCS\x0dE\x0d';
document.getElementById("cmds-" + this.props.jobIndex).value = cmds;
this.setPrinterCommands(cmds);
}
render() {
return (
<div className="col-md-12">
<hr />
<strong>Enter the raw printer commands</strong>
<div className="alert alert-warning">
<small>
Enter the printer's commands you want to send and is supported
by the specified printer (e.g. ESC/POS, ZPL, EPL, etc).
<br />
For non-printable characters, use the JS hex notation (e.g.
\x0D for carriage return, \x1B for ESC)
<br />
<strong>Refer to your target printer programming manual to know how to write the raw commands!</strong>
</small>
</div>
<div>
<small>Predefined Samples for most known RAW Printer Commands</small>
<br />
<button type="button" className="btn btn-light btn-sm" onClick={e => this.setPredefinedCommands('zpl')}><i className="fa fa-arrow-circle-down"></i> Zebra ZPL</button>
&nbsp;&nbsp;
<button type="button" className="btn btn-light btn-sm" onClick={e => this.setPredefinedCommands('epl')}><i className="fa fa-arrow-circle-down"></i> Zebra EPL</button>
&nbsp;&nbsp;
<button type="button" className="btn btn-light btn-sm" onClick={e => this.setPredefinedCommands('escpos')}><i className="fa fa-arrow-circle-down"></i> EPSON ESC/POS</button>
&nbsp;&nbsp;
<button type="button" className="btn btn-light btn-sm" onClick={e => this.setPredefinedCommands('ipl')}><i className="fa fa-arrow-circle-down"></i> Intermec IPL</button>
&nbsp;&nbsp;
<button type="button" className="btn btn-light btn-sm" onClick={e => this.setPredefinedCommands('dpl')}><i className="fa fa-arrow-circle-down"></i> Datamax DPL</button>
</div>
<textarea
id={"cmds-" + this.props.jobIndex}
className="form-control form-control-sm"
onChange={e => this.setPrinterCommands(e.target.value)}
/>
</div>
);
}
}
window.PrintJobForRawCommands = PrintJobForRawCommands;
@@ -0,0 +1,274 @@
class Printers extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedPrinterIndex: 0,
clientPrinter: null,
installedPrinters: [],
printerName: "",
printerNetworkIp: "",
printerNetworkPort: 0,
printerNetworkDns: "",
printerLptPort: "",
printerSerialPort: "",
printerSerialPortBaudRate: 0,
printerSerialPortParity: 0,
printerSerialPortStopBit: 0,
printerSerialPortDataBits: 0,
printerSerialPortFlowControl: 0
};
}
setInstalledPrinters(printersList) {
//no need to re-render
this.state.installedPrinters = printersList;
this.state.printerName = printersList[0];
this.updateClientPrinter();
}
setPrinterState(event) {
this.setState({ [event.target.name]: event.target.value });
this.state[event.target.name] = event.target.value;
this.updateClientPrinter();
}
updateClientPrinter() {
//no need to re-render
if (this.state.selectedPrinterIndex == 0) {
this.state.clientPrinter = new JSPM.DefaultPrinter();
} else if (this.state.selectedPrinterIndex == 1) {
this.state.clientPrinter = new JSPM.UserSelectedPrinter();
} else if (this.state.selectedPrinterIndex == 2) {
this.state.clientPrinter = new JSPM.InstalledPrinter(
this.state.printerName
);
} else if (this.state.selectedPrinterIndex == 3) {
this.state.clientPrinter = new JSPM.NetworkPrinter(
this.state.printerNetworkPort,
this.state.printerNetworkIp,
this.state.printerNetworkDns
);
} else if (this.state.selectedPrinterIndex == 4) {
this.state.clientPrinter = new JSPM.ParallelPortPrinter(
this.state.printerLptPort
);
} else if (this.state.selectedPrinterIndex == 5) {
this.state.clientPrinter = new JSPM.SerialPortPrinter(
this.state.printerSerialPort,
this.state.printerSerialPortBaudRate,
this.state.printerSerialPortParity,
this.state.printerSerialPortStopBits,
this.state.printerSerialPortDataBits,
this.state.printerSerialPortFlowControl
);
}
this.props.onPrinterChange(this.state.clientPrinter);
}
componentDidMount() {
//get client installed printers
JSPM.JSPrintManager.Caller = this;
JSPM.JSPrintManager.getPrinters().then(function(printersList) {
JSPM.JSPrintManager.Caller.setInstalledPrinters(printersList);
});
}
render() {
let netPrinter =
this.props.JobContentType == 0 ? (
<option value="3">Use an IP/Ethernet Printer</option>
) : (
""
);
let lptPrinter =
this.props.JobContentType == 0 ? (
<option value="4">Use a Parallel LPT Port</option>
) : (
""
);
let rs232Printer =
this.props.JobContentType == 0 ? (
<option value="5">Use a Serial (RS232) Port</option>
) : (
""
);
let printerSettings = (
<div>The Printer set as Default in this machine will be used.</div>
);
if (this.state.selectedPrinterIndex == 1) {
printerSettings = (
<div>
The OS Printer Dialog will be displayed at printing time!
</div>
);
} else if (this.state.selectedPrinterIndex == 2) {
let items = this.state.installedPrinters;
printerSettings = (
<div>
Installed Printers
<select
className="form-control form-control-sm"
name="printerName"
onChange={this.setPrinterState.bind(this)}
>
{items.map(function(i) {
let opt = (
<option key={i} value={i}>
{i}
</option>
);
return opt;
})}
</select>
</div>
);
} else if (
this.state.selectedPrinterIndex == 3 &&
this.props.JobContentType == 0
) {
printerSettings = (
<div>
<label>
IP
<input
className="form-control form-control-sm"
name="printerNetworkIp"
onChange={this.setPrinterState.bind(this)}
/>
</label>
<label>
Port
<input
className="form-control form-control-sm"
name="printerNetworkPort"
onChange={this.setPrinterState.bind(this)}
/>
</label>
<label>
DNS Name
<input
className="form-control form-control-sm"
name="printerNetworkDns"
onChange={this.setPrinterState.bind(this)}
/>
</label>
</div>
);
} else if (
this.state.selectedPrinterIndex == 4 &&
this.props.JobContentType == 0
) {
printerSettings = (
<div>
<label>
LPT Port
<input
className="form-control form-control-sm"
name="printerLptPort"
onChange={this.setPrinterState.bind(this)}
/>
</label>
</div>
);
} else if (
this.state.selectedPrinterIndex == 5 &&
this.props.JobContentType == 0
) {
printerSettings = (
<div>
<label>
Serial Port
<input
className="form-control form-control-sm"
name="printerSerialPort"
onChange={this.setPrinterState.bind(this)}
/>
</label>
<label>
Baud Rate
<input
className="form-control form-control-sm"
name="printerSerialPortBaudRate"
onChange={this.setPrinterState.bind(this)}
/>
</label>
<label>
Data Bits
<input
className="form-control form-control-sm"
name="printerSerialPortDataBits"
onChange={this.setPrinterState.bind(this)}
/>
</label>
<label>
Parity
<select
className="form-control form-control-sm"
name="printerSerialPortParity"
onChange={this.setPrinterState.bind(this)}
>
<option value="0">None</option>
<option value="1">Odd</option>
<option value="2">Even</option>
<option value="3">Mark</option>
<option value="4">Space</option>
</select>
</label>
<label>
Stop bits
<select
className="form-control form-control-sm"
name="printerSerialPortStopBits"
onChange={this.setPrinterState.bind(this)}
>
<option value="0">0</option>
<option value="1">1</option>
<option value="3">1.5</option>
<option value="2">2</option>
</select>
</label>
<label>
Flow control
<select
className="form-control form-control-sm"
name="printerSerialPortFlowControl"
onChange={this.setPrinterState.bind(this)}
>
<option value="0">None</option>
<option value="3">XOnXOff</option>
<option value="1">RTS (Request to send)</option>
<option value="2">RTS XOnXOff</option>
</select>
</label>
</div>
);
}
return (
<div className="col-md-12">
<strong>Client Printer</strong>
<select
required
className="form-control form-control-sm"
name="selectedPrinterIndex"
onChange={this.setPrinterState.bind(this)}
>
<option value="0">Default Printer</option>
<option value="1">
Select one through the OS Printer Dialog
</option>
<option value="2">Select an Installed Printer</option>
{netPrinter}
{lptPrinter}
{rs232Printer}
</select>
<br />
<div className="small alert alert-warning">{printerSettings}</div>
</div>
);
}
}
window.Printers = Printers;
@@ -0,0 +1,299 @@
class PrintersInfoSample extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedPrinterIndex: 0,
installedPrinters: []
};
}
setInstalledPrinters(printersList) {
this.setState({ installedPrinters: printersList });
console.log(printersList);
}
setPrinterState(event) {
this.setState({ selectedPrinterIndex: event.target.value });
}
componentDidMount() {
//get client installed printers with detailed info
JSPM.JSPrintManager.Caller = this;
JSPM.JSPrintManager.getPrintersInfo().then(function(printersList) {
JSPM.JSPrintManager.Caller.setInstalledPrinters(printersList);
});
}
render() {
let demoContent;
if (this.state.installedPrinters.length == 0) {
demoContent = (
<div className="row">
<div className="col-md-12">
<div className="text-center">
<img src="loading.gif" id="loadingPrintersInfo" />
<br />
<strong>Getting printers info...</strong>
</div>
</div>
</div>
);
} else {
let isVirtual = true;
let printerPort = this.state.installedPrinters[
this.state.selectedPrinterIndex
].port.toLowerCase();
if (printerPort != "nul" && this.state.installedPrinters[
this.state.selectedPrinterIndex
].BIDIEnabled)
isVirtual = false;
else if (printerPort.indexOf("usb") >= 0 && printerPort.indexOf("?serial=") >= 0)
isVirtual = false;
demoContent = (
<div className="row">
<div className="col-md-12">
<div className="form-group">
<div className="row">
<div className="col-md-3">
<label>Printers:</label>
<select
className="form-control form-control-sm"
onChange={this.setPrinterState.bind(this)}
>
{this.state.installedPrinters.map(function(item, i) {
let opt = (
<option key={i} value={i}>
{item.name}
</option>
);
return opt;
})}
</select>
</div>
<div className="col-md-3">
<label>It seems to be a...</label>
<div>
<h2
className={
isVirtual
? "badge badge-warning"
: "badge badge-info"
}
>
{isVirtual
? "VIRTUAL PRINTER"
: "REAL/PHYSICAL PRINTER"}
</h2>
</div>
</div>
<div className="col-md-3">
<label>Supported Trays:</label>
<select
className="form-control form-control-sm"
name="printerTrayName"
>
{this.state.installedPrinters[
this.state.selectedPrinterIndex
].trays.map(function(item) {
let opt = (
<option key={item} value={item}>
{item}
</option>
);
return opt;
})}
</select>
</div>
<div className="col-md-3">
<label>Supported Papers:</label>
<select
className="form-control form-control-sm"
name="printerPaperName"
>
{this.state.installedPrinters[
this.state.selectedPrinterIndex
].papers.map(function(item) {
let opt = (
<option key={item} value={item}>
{item}
</option>
);
return opt;
})}
</select>
</div>
</div>
<div className="row">
<div className="col-md-12">
<br />
<br />
<table className="table">
<tbody>
<tr>
<td><strong>Port Name:</strong></td>
<td>
{
this.state.installedPrinters[
this.state.selectedPrinterIndex
].port
}
</td>
<td><strong>Horizontal Resolution (dpi):</strong></td>
<td>
{
this.state.installedPrinters[
this.state.selectedPrinterIndex
].XDPI
}
</td>
<td><strong>Vertical Resolution (dpi):</strong></td>
<td>
{
this.state.installedPrinters[
this.state.selectedPrinterIndex
].YDPI
}
</td>
</tr>
<tr>
<td colSpan="2">
<h4>
<span
className={
this.state.installedPrinters[
this.state.selectedPrinterIndex
].connected
? "badge badge-info fa fa-check"
: "badge badge-danger fa fa-close"
}
>
&nbsp;
</span>{" "}
Is Connected?
</h4>
</td>
<td colSpan="2">
<h4>
<span
className={
this.state.installedPrinters[
this.state.selectedPrinterIndex
].default
? "badge badge-info fa fa-check"
: "badge badge-danger fa fa-close"
}
>
&nbsp;
</span>{" "}
Is Default?
</h4>
</td>
<td colSpan="2">
<h4>
<span
className={
this.state.installedPrinters[
this.state.selectedPrinterIndex
].BIDIEnabled
? "badge badge-info fa fa-check"
: "badge badge-danger fa fa-close"
}
>
&nbsp;
</span>{" "}
Is BIDI Enabled?
</h4>
</td>
</tr>
<tr>
<td colSpan="2">
<h4>
<span
className={
this.state.installedPrinters[
this.state.selectedPrinterIndex
].isLocal
? "badge badge-info fa fa-check"
: "badge badge-danger fa fa-close"
}
>
&nbsp;
</span>{" "}
Is Local?
</h4>
</td>
<td colSpan="2">
<h4>
<span
className={
this.state.installedPrinters[
this.state.selectedPrinterIndex
].isNetwork
? "badge badge-info fa fa-check"
: "badge badge-danger fa fa-close"
}
>
&nbsp;
</span>{" "}
Is Network?
</h4>
</td>
<td colSpan="2">
<h4>
<span
className={
this.state.installedPrinters[
this.state.selectedPrinterIndex
].isShared
? "badge badge-info fa fa-check"
: "badge badge-danger fa fa-close"
}
>
&nbsp;
</span>{" "}
Is Shared?
</h4>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
);
}
return (
<div>
<div className="row">
<div className="col-md-1">
<button
className="btn btn-dark btn-lg"
onClick={() => this.props.setSample(0)}
>
<i className="fa fa-arrow-left" />
</button>
</div>
<div className="col-md-11">
<h2 className="text-center">
<i className="fa fa-print" />&nbsp;Printers Info
</h2>
<hr />
</div>
</div>
{demoContent}
</div>
);
}
}
window.PrintersInfoSample = PrintersInfoSample;
@@ -0,0 +1,113 @@
class PrintingFilesSample extends React.Component {
constructor(props) {
super(props);
this.state = {
job: null,
clientPrinter: null,
printFiles: []
};
}
doPrinting() {
if (this.state.job) {
let cpj = this.state.job;
cpj.sendToClient();
}
}
updateJob() {
var cpj = new JSPM.ClientPrintJob();
cpj.clientPrinter = this.state.clientPrinter;
if (this.state.printFiles) {
let files = this.state.printFiles;
for (let j = 0; j < files.length; j++) {
let my_file;
if (files[j].name)
my_file = new JSPM.PrintFile(
files[j],
JSPM.FileSourceType.BLOB,
files[j].name,
1
);
else
my_file = new JSPM.PrintFile(
files[j],
JSPM.FileSourceType.URL,
"myFileToPrint." + files[j].split(".").pop(),
1
);
cpj.files.push(my_file);
}
}
//no need to re-render
this.state.job = cpj;
}
onPrinterChange(newPrinter) {
//No need to re-render!
this.state.clientPrinter = newPrinter;
this.updateJob();
}
onPrintFilesChange(newFiles) {
//No need to re-render!
this.state.printFiles = newFiles;
this.updateJob();
}
render() {
return (
<div>
<div className="row">
<div className="col-md-1">
<button
className="btn btn-dark btn-lg"
onClick={() => this.props.setSample(0)}
>
<i className="fa fa-arrow-left" />
</button>
</div>
<div className="col-md-11">
<h2 className="text-center">
<i className="fa fa-file-image-o" />&nbsp;Print Images &amp;
Docs
</h2>
<hr />
</div>
</div>
<div className="card-body">
<div className="row">
<Printers
JobContentType={1}
onPrinterChange={this.onPrinterChange.bind(this)}
/>
</div>
<div className="row">
<PrintJobForFiles
jobIndex={0}
onPrintFilesChange={this.onPrintFilesChange.bind(this)}
/>
</div>
</div>
<div className="row">
<div className="col-md-12">
<br />
<div className="text-center">
<button
className="btn btn-success btn-lg"
onClick={this.doPrinting.bind(this)}
>
<i className="fa fa-print" /> Print Now...
</button>
</div>
</div>
</div>
</div>
);
}
}
window.PrintingFilesSample = PrintingFilesSample;
@@ -0,0 +1,121 @@
class PrintingMultiplePrintJobsSample extends React.Component {
constructor(props) {
super(props);
this.state = {
jobs: []
};
}
removeJob(i) {
let arr = this.state.jobs;
arr.splice(i, 1);
this.setState({ jobs: arr });
}
addJob() {
let arr = this.state.jobs;
arr.push(new JSPM.ClientPrintJob());
this.setState({ jobs: arr });
}
updateJob(i, pj) {
//no need to re-render
this.state.jobs[i] = pj;
}
doPrinting() {
var cpjg = new JSPM.ClientPrintJobGroup();
for (var i = 0; i < this.state.jobs.length; i++) {
cpjg.jobs.push(this.state.jobs[i]);
}
cpjg.sendToClient();
}
render() {
let printButton;
if (this.state.jobs.length > 0) {
printButton = (
<div className="row">
<div className="col-md-12">
<br />
<div className="text-center">
<button
className="btn btn-success btn-lg"
onClick={this.doPrinting.bind(this)}
>
<i className="fa fa-print" /> Print Now...
</button>
</div>
</div>
</div>
);
}
return (
<div>
<div className="row">
<div className="col-md-1">
<button
className="btn btn-dark btn-lg"
onClick={() => this.props.setSample(0)}
>
<i className="fa fa-arrow-left" />
</button>
</div>
<div className="col-md-11">
<h2 className="text-center">
<i className="fa fa-barcode" />+
<i className="fa fa-file-text" />&nbsp;Print Multiple Jobs
in one shot!
</h2>
<hr />
</div>
</div>
<div className="row">
<div className="col-md-3">
<button
className="btn btn-info btn-lg"
onClick={this.addJob.bind(this)}
>
<i className="fa fa-plus" /> Add Print Job
</button>
</div>
<div className="col-md-9">
<div
className="alert alert-warning alert-dismissible fade show"
role="alert"
>
<i className="fa fa-info-circle" />{" "}
<small>
You can print raw commands and files to different client
printers if needed!
</small>
<button
type="button"
className="close"
data-dismiss="alert"
aria-label="Close"
>
<span aria-hidden="true">&times;</span>
</button>
</div>
</div>
</div>
<div id="accordion">
{this.state.jobs.map((pj, i) => {
return (
<PrintJob
jobIndex={i}
removeJobHandler={this.removeJob.bind(this)}
updateJobHandler={this.updateJob.bind(this)}
/>
);
})}
</div>
{printButton}
</div>
);
}
}
window.PrintingMultiplePrintJobsSample = PrintingMultiplePrintJobsSample;
@@ -0,0 +1,365 @@
class PrintingPDFSample extends React.Component {
constructor(props) {
super(props);
this.state = {
pdfFile: null,
selectedPrinterIndex: 0,
installedPrinters: [],
printerName: "",
printerTrayName: "",
printerPaperName: "",
printAnnotations: false,
printAsGrayscale: false,
printInReverseOrder: false,
printRange: "",
printRotation: "None",
job: null
};
}
setPdfFile(event) {
//no need to re-render
if (event.target.name == "input-local-pdf-file")
this.state.pdfFile = Array.from(event.target.files);
else this.state.pdfFile = [event.target.value];
}
setInstalledPrinters(printersList) {
this.setState({ installedPrinters: printersList });
this.state.printerName = printersList[0].name;
this.updatePrintJob();
}
setPrinterState(event) {
this.setState({ selectedPrinterIndex: event.target.value });
this.state.printerName = this.state.installedPrinters[
event.target.value
].name;
this.updatePrintJob();
}
setData(event) {
//no need for re-render
this.state[event.target.name] = event.target.checked
? event.target.checked
: event.target.value;
this.updatePrintJob();
}
f;
updatePrintJob() {
//no need to re-render
let cpj = new JSPM.ClientPrintJob();
cpj.clientPrinter = new JSPM.InstalledPrinter(this.state.printerName, false, this.state.printerTrayName, this.state.printerPaperName);
if (this.state.pdfFile) {
let myPdfFile;
if (this.state.pdfFile[0].name)
myPdfFile = new JSPM.PrintFilePDF(
this.state.pdfFile[0],
JSPM.FileSourceType.BLOB,
this.state.pdfFile[0].name,
1
);
else
myPdfFile = new JSPM.PrintFilePDF(
this.state.pdfFile[0],
JSPM.FileSourceType.URL,
"myFileToPrint.pdf",
1
);
myPdfFile.printAnnotations = this.state.printAnnotations;
myPdfFile.printAsGrayscale = this.state.printAsGrayscale;
myPdfFile.printInReverseOrder = this.state.printInReverseOrder;
myPdfFile.printRange = this.state.printRange;
myPdfFile.printRotation =
JSPM.PrintRotation[this.state.printRotation];
cpj.files.push(myPdfFile);
}
this.state.job = cpj;
}
componentDidMount() {
//get client installed printers with detailed info
JSPM.JSPrintManager.Caller = this;
JSPM.JSPrintManager.getPrintersInfo().then(function(printersList) {
JSPM.JSPrintManager.Caller.setInstalledPrinters(printersList);
});
}
doPrinting() {
if (this.state.job) {
let cpj = this.state.job;
cpj.sendToClient();
}
}
render() {
let demoContent;
if (this.state.installedPrinters.length == 0) {
demoContent = (
<div className="row">
<div className="col-md-12">
<div className="text-center">
<img src="loading.gif" id="loadingPrintersInfo" />
<br />
<strong>Getting printers info...</strong>
</div>
</div>
</div>
);
} else {
demoContent = (
<div className="row">
<div className="col-md-12">
<div className="form-group">
<div className="row">
<div className="col-md-12">
<strong>PDF File to print</strong>
<ul
className="nav nav-tabs"
id="myTabPdf"
role="tablist"
>
<li className="nav-item">
<a
className="nav-link active"
id="local-pdf-file-tab"
data-toggle="tab"
href="#local-pdf-file"
role="tab"
aria-controls="local-pdf-file"
aria-selected="true"
>
Local PDF File
</a>
</li>
<li className="nav-item">
<a
className="nav-link"
id="remote-pdf-file-tab"
data-toggle="tab"
href="#remote-pdf-file"
role="tab"
aria-controls="remote-pdf-file"
aria-selected="false"
>
PDF File from URL
</a>
</li>
</ul>
<div className="tab-content" id="myTabPdfContent">
<div
className="tab-pane fade show active"
id="local-pdf-file"
role="tabpanel"
aria-labelledby="local-pdf-file"
>
<br />
<input
name="input-local-pdf-file"
type="file"
className="form-control-file"
onChange={this.setPdfFile.bind(this)}
/>
</div>
<div
className="tab-pane fade"
id="remote-pdf-file"
role="tabpanel"
aria-labelledby="remote-pdf-file"
>
<br />
URL for PDF File
<input
name="input-file-url"
className="form-control form-control-sm"
onChange={this.setPdfFile.bind(this)}
/>
</div>
</div>
</div>
</div>
<hr />
<div className="row">
<div className="col-md-12">
<strong>Target Printer</strong>
</div>
</div>
<div className="row">
<div className="col-md-3">
<label>Printer:</label>
<select
className="form-control form-control-sm"
onChange={this.setPrinterState.bind(this)}
>
{this.state.installedPrinters.map(function(item, i) {
let opt = (
<option key={i} value={i}>
{item.name}
</option>
);
return opt;
})}
</select>
</div>
<div className="col-md-3">
<label>Tray:</label>
<select
className="form-control form-control-sm"
name="printerTrayName"
onChange={this.setData.bind(this)}
>
{this.state.installedPrinters[
this.state.selectedPrinterIndex
].trays.map(function(item, i) {
let opt = (
<option key={i} value={item}>
{item}
</option>
);
return opt;
})}
</select>
</div>
<div className="col-md-3">
<label>Paper:</label>
<select
className="form-control form-control-sm"
name="printerPaperName"
onChange={this.setData.bind(this)}
>
{this.state.installedPrinters[
this.state.selectedPrinterIndex
].papers.map(function(item, i) {
let opt = (
<option key={i} value={item}>
{item}
</option>
);
return opt;
})}
</select>
</div>
<div className="col-md-3">
<label>Print Rotation (Clockwise):</label>
<select
className="form-control form-control-sm"
name="printRotation"
onChange={this.setData.bind(this)}
>
<option>None</option>
<option>Rot90</option>
<option>Rot180</option>
<option>Rot270</option>
</select>
</div>
</div>
<br />
<div className="row">
<div className="col-md-3">
<label>Pages Range: [e.g. 1,2,3,10-15]</label>
<input
type="text"
className="form-control form-control-sm"
name="printRange"
onChange={this.setData.bind(this)}
/>
</div>
<div className="col-md-3">
<div className="checkbox">
<label>
<input
id="printInReverseOrder"
type="checkbox"
name="printInReverseOrder"
onChange={this.setData.bind(this)}
/>
Print In Reverse Order?
</label>
</div>
</div>
<div className="col-md-3">
<div className="checkbox">
<label>
<input
id="chkPrintAnnotations"
type="checkbox"
name="printAnnotations"
onChange={this.setData.bind(this)}
/>
Print Annotations?{" "}
<span className="badge badge-info">
Windows Only
</span>
</label>
</div>
</div>
<div className="col-md-3">
<div className="checkbox">
<label>
<input
id="chkPrintAsGrayscale"
type="checkbox"
name="printAsGrayscale"
onChange={this.setData.bind(this)}
/>
Print As Grayscale?{" "}
<span className="badge badge-info">
Windows Only
</span>
</label>
</div>
</div>
</div>
<div className="row">
<div className="col-md-12">
<br />
<div className="text-center">
<button
className="btn btn-success btn-lg"
onClick={this.doPrinting.bind(this)}
>
<i className="fa fa-print" /> Print PDF Now...
</button>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
return (
<div>
<div className="row">
<div className="col-md-1">
<button
className="btn btn-dark btn-lg"
onClick={() => this.props.setSample(0)}
>
<i className="fa fa-arrow-left" />
</button>
</div>
<div className="col-md-11">
<h2 className="text-center">
<i className="fa fa-file-pdf-o" />&nbsp;Advanced PDF
Printing
</h2>
<hr />
</div>
</div>
{demoContent}
</div>
);
}
}
window.PrintingPDFSample = PrintingPDFSample;
@@ -0,0 +1,92 @@
class PrintingRawCommandsSample extends React.Component {
constructor(props) {
super(props);
this.state = {
job: null,
clientPrinter: null,
printerCommands: ""
};
}
doPrinting() {
if (this.state.job) {
let cpj = this.state.job;
cpj.sendToClient();
}
}
updateJob() {
var cpj = new JSPM.ClientPrintJob();
cpj.clientPrinter = this.state.clientPrinter;
cpj.printerCommands = this.state.printerCommands;
//no need to re-render
this.state.job = cpj;
}
onPrinterChange(newPrinter) {
//No need to re-render!
this.state.clientPrinter = newPrinter;
this.updateJob();
}
onPrinterCommandsChange(newPrinterCommands) {
//No need to re-render!
this.state.printerCommands = newPrinterCommands;
this.updateJob();
}
render() {
return (
<div>
<div className="row">
<div className="col-md-1">
<button
className="btn btn-dark btn-lg"
onClick={() => this.props.setSample(0)}
>
<i className="fa fa-arrow-left" />
</button>
</div>
<div className="col-md-11">
<h2 className="text-center">
<i className="fa fa-barcode" />&nbsp;Raw Data Printing
</h2>
<hr />
</div>
</div>
<div className="card-body">
<div className="row">
<Printers
JobContentType={0}
onPrinterChange={this.onPrinterChange.bind(this)}
/>
</div>
<div className="row">
<PrintJobForRawCommands
jobIndex={0}
onPrinterCommandsChange={this.onPrinterCommandsChange.bind(
this
)}
/>
</div>
</div>
<div className="row">
<div className="col-md-12">
<br />
<div className="text-center">
<button
className="btn btn-success btn-lg"
onClick={this.doPrinting.bind(this)}
>
<i className="fa fa-print" /> Print Now...
</button>
</div>
</div>
</div>
</div>
);
}
}
window.PrintingRawCommandsSample = PrintingRawCommandsSample;
@@ -0,0 +1,419 @@
class PrintingTXTSample extends React.Component {
constructor(props) {
super(props);
this.state = {
txtContent: null,
selectedPrinterIndex: 0,
installedPrinters: [],
printerName: "",
printerTrayName: "",
printerPaperName: "",
fontName: "Arial",
fontSize: 8,
fontBold: false,
fontItalic: false,
fontUnderline: false,
fontStrikethrough: false,
textAlign: "Left",
fontColor: "#000000",
printOrientation: "Portrait",
job: null
};
}
setInstalledPrinters(printersList) {
this.setState({ installedPrinters: printersList });
this.state.printerName = printersList[0].name;
this.updatePrintJob();
}
setPrinterState(event) {
this.setState({ selectedPrinterIndex: event.target.value });
this.state.printerName = this.state.installedPrinters[
event.target.value
].name;
this.updatePrintJob();
}
setData(event) {
//no need for re-render
this.state[event.target.name] = event.target.checked
? event.target.checked
: event.target.value;
this.updatePrintJob();
}
setFontStyle(event) {
//no need for re-render
var val = event.currentTarget.classList.contains("active");
var name = event.currentTarget.querySelector("input").name;
this.state[name] = val;
this.updatePrintJob();
}
setTextAlign(event) {
//no need for re-render
var val = event.currentTarget.classList.contains("active");
var name = event.currentTarget.querySelector("input").name;
var textAlign = "Left";
if (val && name == "CenterAlign") textAlign = "Center";
if (val && name == "RightAlign") textAlign = "Right";
if (val && name == "JustifyAlign") textAlign = "Justify";
this.state["textAlign"] = textAlign;
this.updatePrintJob();
}
updatePrintJob() {
//no need to re-render
let cpj = new JSPM.ClientPrintJob();
cpj.clientPrinter = new JSPM.InstalledPrinter(this.state.printerName, false, this.state.printerTrayName, this.state.printerPaperName);
if (this.state.txtContent) {
let myTxtFile = new JSPM.PrintFileTXT(
this.state.txtContent,
"myFileToPrint.txt",
1
);
myTxtFile.textAligment = JSPM.TextAlignment[this.state.textAlign];
myTxtFile.fontName = this.state.fontName;
myTxtFile.fontBold = this.state.fontBold;
myTxtFile.fontItalic = this.state.fontItalic;
myTxtFile.fontUnderline = this.state.fontUnderline;
myTxtFile.fontStrikethrough = this.state.fontStrikethrough;
myTxtFile.fontSize = this.state.fontSize;
myTxtFile.fontColor = this.state.fontColor;
myTxtFile.printOrientation =
JSPM.PrintOrientation[this.state.printOrientation];
cpj.files.push(myTxtFile);
}
this.state.job = cpj;
}
componentDidMount() {
//get client installed printers with detailed info
JSPM.JSPrintManager.Caller = this;
JSPM.JSPrintManager.getPrintersInfo().then(function(printersList) {
JSPM.JSPrintManager.Caller.setInstalledPrinters(printersList);
});
}
doPrinting() {
if (this.state.job) {
let cpj = this.state.job;
cpj.sendToClient();
}
}
render() {
let demoContent;
if (this.state.installedPrinters.length == 0) {
demoContent = (
<div className="row">
<div className="col-md-12">
<div className="text-center">
<img src="loading.gif" id="loadingPrintersInfo" />
<br />
<strong>Getting printers info...</strong>
</div>
</div>
</div>
);
} else {
demoContent = (
<div className="row">
<div className="col-md-12">
<div className="form-group">
<div className="row">
<div className="col-md-12">
<strong>Enter Text to print</strong>
</div>
</div>
<div className="row">
<div className="col-md-12">
<div className="btn-toolbar" role="toolbar">
<div className="btn-group btn-group-sm" role="group">
<select
className="form-control form-control-sm"
name="fontName"
onChange={this.setData.bind(this)}
>
<option>Arial</option>
<option>Courier New</option>
<option>Comic Sans MS</option>
<option>Verdana</option>
</select>
</div>
<div className="btn-group btn-group-sm" role="group">
<select
className="form-control form-control-sm"
name="fontSize"
onChange={this.setData.bind(this)}
>
<option>8</option>
<option>10</option>
<option>12</option>
<option>14</option>
<option>16</option>
</select>
</div>
<div
className="btn-group-toggle btn-group-sm"
data-toggle="buttons"
>
<label
className="btn btn-light"
onClick={this.setFontStyle.bind(this)}
>
<input
type="checkbox"
autoComplete="off"
name="fontBold"
/>
<i className="fa fa-bold" aria-hidden="true" />
</label>
<label
className="btn btn-light"
onClick={this.setFontStyle.bind(this)}
>
<input
type="checkbox"
autoComplete="off"
name="fontItalic"
/>
<i className="fa fa-italic" aria-hidden="true" />
</label>
<label
className="btn btn-light"
onClick={this.setFontStyle.bind(this)}
>
<input
type="checkbox"
autoComplete="off"
name="fontUnderline"
/>
<i
className="fa fa-underline"
aria-hidden="true"
/>
</label>
<label
className="btn btn-light"
onClick={this.setFontStyle.bind(this)}
>
<input
type="checkbox"
autoComplete="off"
name="fontStrikethrough"
/>
<i
className="fa fa-strikethrough"
aria-hidden="true"
/>
</label>
</div>
<div
className="btn-group btn-group-sm btn-group-toggle"
data-toggle="buttons"
>
<label
className="btn btn-light active"
onClick={this.setTextAlign.bind(this)}
>
<input
type="radio"
name="LeftAlign"
autoComplete="off"
defaultChecked
/>
<i
className="fa fa-align-left"
aria-hidden="true"
/>
</label>
<label
className="btn btn-light"
onClick={this.setTextAlign.bind(this)}
>
<input
type="radio"
name="CenterAlign"
autoComplete="off"
/>
<i
className="fa fa-align-center"
aria-hidden="true"
/>
</label>
<label
className="btn btn-light"
onClick={this.setTextAlign.bind(this)}
>
<input
type="radio"
name="RightAlign"
autoComplete="off"
/>
<i
className="fa fa-align-right"
aria-hidden="true"
/>
</label>
<label
className="btn btn-light"
onClick={this.setTextAlign.bind(this)}
>
<input
type="radio"
name="JustifyAlign"
autoComplete="off"
/>
<i
className="fa fa-align-justify"
aria-hidden="true"
/>
</label>
</div>
<div className="btn-group btn-group-sm" role="group">
<input
type="color"
name="fontColor"
defaultValue="#000000"
onChange={this.setData.bind(this)}
/>
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-md-12">
<textarea
className="form-control form-control-sm"
name="txtContent"
onChange={this.setData.bind(this)}
/>
</div>
</div>
<div className="row">
<div className="col-md-12">
<strong>Target Printer</strong>
</div>
</div>
<div className="row">
<div className="col-md-3">
<label>Printer:</label>
<select
className="form-control form-control-sm"
onChange={this.setPrinterState.bind(this)}
>
{this.state.installedPrinters.map(function(item, i) {
let opt = (
<option key={i} value={i}>
{item.name}
</option>
);
return opt;
})}
</select>
</div>
<div className="col-md-3">
<label>Tray:</label>
<select
className="form-control form-control-sm"
name="printerTrayName"
onChange={this.setData.bind(this)}
>
{this.state.installedPrinters[
this.state.selectedPrinterIndex
].trays.map(function(item) {
let opt = (
<option key={item} value={item}>
{item}
</option>
);
return opt;
})}
</select>
</div>
<div className="col-md-3">
<label>Paper:</label>
<select
className="form-control form-control-sm"
name="printerPaperName"
onChange={this.setData.bind(this)}
>
{this.state.installedPrinters[
this.state.selectedPrinterIndex
].papers.map(function(item) {
let opt = (
<option key={item} value={item}>
{item}
</option>
);
return opt;
})}
</select>
</div>
<div className="col-md-3">
<label>Print Orientation:</label>
<select
className="form-control form-control-sm"
name="printRotation"
onChange={this.setData.bind(this)}
>
<option>Portrait</option>
<option>Landscape</option>
</select>
</div>
</div>
<br />
<div className="row">
<div className="col-md-12">
<br />
<div className="text-center">
<button
className="btn btn-success btn-lg"
onClick={this.doPrinting.bind(this)}
>
<i className="fa fa-print" /> Print Text Now...
</button>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
return (
<div>
<div className="row">
<div className="col-md-1">
<button
className="btn btn-dark btn-lg"
onClick={() => this.props.setSample(0)}
>
<i className="fa fa-arrow-left" />
</button>
</div>
<div className="col-md-11">
<h2 className="text-center">
<i className="fa fa-file-text-o" />&nbsp;Advanced TXT
Printing
</h2>
<hr />
</div>
</div>
{demoContent}
</div>
);
}
}
window.PrintingTXTSample = PrintingTXTSample;
@@ -0,0 +1,18 @@
class WebsiteBlackListed extends React.Component {
render() {
return (
<div>
<h2>This site is blacklisted!</h2>
<hr />
This website is
<strong>
Blacklisted and cannot print through JSPrintManager
</strong>
<br />
<br />
</div>
);
}
}
window.WebsiteBlackListed = WebsiteBlackListed;
@@ -0,0 +1,416 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Page not found</title>
<style>
html {font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
body {margin:0}
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
nav,
section,
summary {display:block}
audio,
canvas,
progress,
video {display:inline-block;vertical-align:baseline}
audio:not([controls]) {display:none;height:0}
[hidden],
template {display:none}
a {background:transparent}
a:active,
a:hover {outline:0}
abbr[title] {border-bottom:1px dotted}
b,
strong {font-weight:bold}
dfn {font-style:italic}
h1 {font-size:2em;margin:0.67em 0}
mark {background:#ff0;color:#000}
small {font-size:80%}
sub,
sup {font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup {top:-0.5em}
sub {bottom:-0.25em}
img {border:0}
svg:not(:root) {overflow:hidden}
figure {margin:1em 40px}
hr {-moz-box-sizing:content-box;box-sizing:content-box;height:0}
pre {overflow:auto}
code,
kbd,
pre,
samp {font-family:monospace,monospace;font-size:1em}
button,
input,
optgroup,
select,
textarea {color:inherit;font:inherit;margin:0}
button {overflow:visible}
button,
select {text-transform:none}
button,
html input[type="button"],
input[type="reset"],
input[type="submit"] {-webkit-appearance:button;cursor:pointer}
button[disabled],
html input[disabled] {cursor:default}
button::-moz-focus-inner,
input::-moz-focus-inner {border:0;padding:0}
input {line-height:normal}
input[type="checkbox"],
input[type="radio"] {box-sizing:border-box;padding:0}
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {height:auto}
input[type="search"] {-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {-webkit-appearance:none}
fieldset {border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}
legend {border:0;padding:0}
textarea {overflow:auto}
optgroup {font-weight:bold}
table {border-collapse:collapse;border-spacing:0;table-layout:auto;word-wrap:break-word;word-break:break-all}
td,
th {padding:0}
*,
*:before,
*:after {-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}
html {font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}
body {font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:14px;line-height:1.42857143;color:#333;background-color:#f9f9f9}
input,
button,
select,
textarea {font-family:inherit;font-size:inherit;line-height:inherit}
button,
input,
select[multiple],
textarea {background-image:none}
a {color:#0181b9;text-decoration:none}
a:hover,
a:focus {color:#001721;text-decoration:underline}
a:focus {outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}
img {vertical-align:middle}
.img-responsive {display:block;max-width:100%;height:auto}
.img-rounded {-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}
.img-circle {border-radius:50%}
hr {margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}
.sr-only {position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);border:0}
@media print {* {text-shadow:none !important;color:#000 !important;background:transparent !important;box-shadow:none !important }a,a:visited {text-decoration:underline }a[href]:after {content:" (" attr(href) ")" }abbr[title]:after {content:" (" attr(title) ")" }a[href^="javascript:"]:after,a[href^="#"]:after {content:"" }pre,blockquote {border:1px solid #999;page-break-inside:avoid }thead {display:table-header-group }tr,img {page-break-inside:avoid }img {max-width:100% !important }p,h2,h3 {orphans:3;widows:3 }h2,h3 {page-break-after:avoid }select {background:#fff !important }.navbar {display:none }.table td,.table th {background-color:#fff !important }.btn >.caret,.dropup >.btn >.caret {border-top-color:#000 !important }.label {border:1px solid #000 }.table {border-collapse:collapse !important }.table-bordered th,.table-bordered td {border:1px solid #ddd !important }}
.container {margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}
@media (min-width:768px) {.container {width:750px }}
@media (min-width:992px) {.container {width:970px }}
@media (min-width:1200px) {.container {width:1170px }}
.container-fluid {margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}
.row {margin-left:-15px;margin-right:-15px}
.row-flush {margin-left:0;margin-right:0}
.row-flush [class*="col-"] {padding-left:0 !important;padding-right:0 !important}
.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12 {position:relative;min-height:1px;padding-left:15px;padding-right:15px}
.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12 {float:left}
.col-xs-12 {width:100%}
.col-xs-11 {width:91.66666667%}
.col-xs-10 {width:83.33333333%}
.col-xs-9 {width:75%}
.col-xs-8 {width:66.66666667%}
.col-xs-7 {width:58.33333333%}
.col-xs-6 {width:50%}
.col-xs-5 {width:41.66666667%}
.col-xs-4 {width:33.33333333%}
.col-xs-3 {width:25%}
.col-xs-2 {width:16.66666667%}
.col-xs-1 {width:8.33333333%}
.col-xs-pull-12 {right:100%}
.col-xs-pull-11 {right:91.66666667%}
.col-xs-pull-10 {right:83.33333333%}
.col-xs-pull-9 {right:75%}
.col-xs-pull-8 {right:66.66666667%}
.col-xs-pull-7 {right:58.33333333%}
.col-xs-pull-6 {right:50%}
.col-xs-pull-5 {right:41.66666667%}
.col-xs-pull-4 {right:33.33333333%}
.col-xs-pull-3 {right:25%}
.col-xs-pull-2 {right:16.66666667%}
.col-xs-pull-1 {right:8.33333333%}
.col-xs-pull-0 {right:0%}
.col-xs-push-12 {left:100%}
.col-xs-push-11 {left:91.66666667%}
.col-xs-push-10 {left:83.33333333%}
.col-xs-push-9 {left:75%}
.col-xs-push-8 {left:66.66666667%}
.col-xs-push-7 {left:58.33333333%}
.col-xs-push-6 {left:50%}
.col-xs-push-5 {left:41.66666667%}
.col-xs-push-4 {left:33.33333333%}
.col-xs-push-3 {left:25%}
.col-xs-push-2 {left:16.66666667%}
.col-xs-push-1 {left:8.33333333%}
.col-xs-push-0 {left:0%}
.col-xs-offset-12 {margin-left:100%}
.col-xs-offset-11 {margin-left:91.66666667%}
.col-xs-offset-10 {margin-left:83.33333333%}
.col-xs-offset-9 {margin-left:75%}
.col-xs-offset-8 {margin-left:66.66666667%}
.col-xs-offset-7 {margin-left:58.33333333%}
.col-xs-offset-6 {margin-left:50%}
.col-xs-offset-5 {margin-left:41.66666667%}
.col-xs-offset-4 {margin-left:33.33333333%}
.col-xs-offset-3 {margin-left:25%}
.col-xs-offset-2 {margin-left:16.66666667%}
.col-xs-offset-1 {margin-left:8.33333333%}
.col-xs-offset-0 {margin-left:0%}
@media (min-width:768px) {.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12 {float:left }.col-sm-12 {width:100% }.col-sm-11 {width:91.66666667% }.col-sm-10 {width:83.33333333% }.col-sm-9 {width:75% }.col-sm-8 {width:66.66666667% }.col-sm-7 {width:58.33333333% }.col-sm-6 {width:50% }.col-sm-5 {width:41.66666667% }.col-sm-4 {width:33.33333333% }.col-sm-3 {width:25% }.col-sm-2 {width:16.66666667% }.col-sm-1 {width:8.33333333% }.col-sm-pull-12 {right:100% }.col-sm-pull-11 {right:91.66666667% }.col-sm-pull-10 {right:83.33333333% }.col-sm-pull-9 {right:75% }.col-sm-pull-8 {right:66.66666667% }.col-sm-pull-7 {right:58.33333333% }.col-sm-pull-6 {right:50% }.col-sm-pull-5 {right:41.66666667% }.col-sm-pull-4 {right:33.33333333% }.col-sm-pull-3 {right:25% }.col-sm-pull-2 {right:16.66666667% }.col-sm-pull-1 {right:8.33333333% }.col-sm-pull-0 {right:0% }.col-sm-push-12 {left:100% }.col-sm-push-11 {left:91.66666667% }.col-sm-push-10 {left:83.33333333% }.col-sm-push-9 {left:75% }.col-sm-push-8 {left:66.66666667% }.col-sm-push-7 {left:58.33333333% }.col-sm-push-6 {left:50% }.col-sm-push-5 {left:41.66666667% }.col-sm-push-4 {left:33.33333333% }.col-sm-push-3 {left:25% }.col-sm-push-2 {left:16.66666667% }.col-sm-push-1 {left:8.33333333% }.col-sm-push-0 {left:0% }.col-sm-offset-12 {margin-left:100% }.col-sm-offset-11 {margin-left:91.66666667% }.col-sm-offset-10 {margin-left:83.33333333% }.col-sm-offset-9 {margin-left:75% }.col-sm-offset-8 {margin-left:66.66666667% }.col-sm-offset-7 {margin-left:58.33333333% }.col-sm-offset-6 {margin-left:50% }.col-sm-offset-5 {margin-left:41.66666667% }.col-sm-offset-4 {margin-left:33.33333333% }.col-sm-offset-3 {margin-left:25% }.col-sm-offset-2 {margin-left:16.66666667% }.col-sm-offset-1 {margin-left:8.33333333% }.col-sm-offset-0 {margin-left:0% }}
@media (min-width:992px) {.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12 {float:left }.col-md-12 {width:100% }.col-md-11 {width:91.66666667% }.col-md-10 {width:83.33333333% }.col-md-9 {width:75% }.col-md-8 {width:66.66666667% }.col-md-7 {width:58.33333333% }.col-md-6 {width:50% }.col-md-5 {width:41.66666667% }.col-md-4 {width:33.33333333% }.col-md-3 {width:25% }.col-md-2 {width:16.66666667% }.col-md-1 {width:8.33333333% }.col-md-pull-12 {right:100% }.col-md-pull-11 {right:91.66666667% }.col-md-pull-10 {right:83.33333333% }.col-md-pull-9 {right:75% }.col-md-pull-8 {right:66.66666667% }.col-md-pull-7 {right:58.33333333% }.col-md-pull-6 {right:50% }.col-md-pull-5 {right:41.66666667% }.col-md-pull-4 {right:33.33333333% }.col-md-pull-3 {right:25% }.col-md-pull-2 {right:16.66666667% }.col-md-pull-1 {right:8.33333333% }.col-md-pull-0 {right:0% }.col-md-push-12 {left:100% }.col-md-push-11 {left:91.66666667% }.col-md-push-10 {left:83.33333333% }.col-md-push-9 {left:75% }.col-md-push-8 {left:66.66666667% }.col-md-push-7 {left:58.33333333% }.col-md-push-6 {left:50% }.col-md-push-5 {left:41.66666667% }.col-md-push-4 {left:33.33333333% }.col-md-push-3 {left:25% }.col-md-push-2 {left:16.66666667% }.col-md-push-1 {left:8.33333333% }.col-md-push-0 {left:0% }.col-md-offset-12 {margin-left:100% }.col-md-offset-11 {margin-left:91.66666667% }.col-md-offset-10 {margin-left:83.33333333% }.col-md-offset-9 {margin-left:75% }.col-md-offset-8 {margin-left:66.66666667% }.col-md-offset-7 {margin-left:58.33333333% }.col-md-offset-6 {margin-left:50% }.col-md-offset-5 {margin-left:41.66666667% }.col-md-offset-4 {margin-left:33.33333333% }.col-md-offset-3 {margin-left:25% }.col-md-offset-2 {margin-left:16.66666667% }.col-md-offset-1 {margin-left:8.33333333% }.col-md-offset-0 {margin-left:0% }}
@media (min-width:1200px) {.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12 {float:left }.col-lg-12 {width:100% }.col-lg-11 {width:91.66666667% }.col-lg-10 {width:83.33333333% }.col-lg-9 {width:75% }.col-lg-8 {width:66.66666667% }.col-lg-7 {width:58.33333333% }.col-lg-6 {width:50% }.col-lg-5 {width:41.66666667% }.col-lg-4 {width:33.33333333% }.col-lg-3 {width:25% }.col-lg-2 {width:16.66666667% }.col-lg-1 {width:8.33333333% }.col-lg-pull-12 {right:100% }.col-lg-pull-11 {right:91.66666667% }.col-lg-pull-10 {right:83.33333333% }.col-lg-pull-9 {right:75% }.col-lg-pull-8 {right:66.66666667% }.col-lg-pull-7 {right:58.33333333% }.col-lg-pull-6 {right:50% }.col-lg-pull-5 {right:41.66666667% }.col-lg-pull-4 {right:33.33333333% }.col-lg-pull-3 {right:25% }.col-lg-pull-2 {right:16.66666667% }.col-lg-pull-1 {right:8.33333333% }.col-lg-pull-0 {right:0% }.col-lg-push-12 {left:100% }.col-lg-push-11 {left:91.66666667% }.col-lg-push-10 {left:83.33333333% }.col-lg-push-9 {left:75% }.col-lg-push-8 {left:66.66666667% }.col-lg-push-7 {left:58.33333333% }.col-lg-push-6 {left:50% }.col-lg-push-5 {left:41.66666667% }.col-lg-push-4 {left:33.33333333% }.col-lg-push-3 {left:25% }.col-lg-push-2 {left:16.66666667% }.col-lg-push-1 {left:8.33333333% }.col-lg-push-0 {left:0% }.col-lg-offset-12 {margin-left:100% }.col-lg-offset-11 {margin-left:91.66666667% }.col-lg-offset-10 {margin-left:83.33333333% }.col-lg-offset-9 {margin-left:75% }.col-lg-offset-8 {margin-left:66.66666667% }.col-lg-offset-7 {margin-left:58.33333333% }.col-lg-offset-6 {margin-left:50% }.col-lg-offset-5 {margin-left:41.66666667% }.col-lg-offset-4 {margin-left:33.33333333% }.col-lg-offset-3 {margin-left:25% }.col-lg-offset-2 {margin-left:16.66666667% }.col-lg-offset-1 {margin-left:8.33333333% }.col-lg-offset-0 {margin-left:0% }}
.clearfix:before,
.clearfix:after,
.container:before,
.container:after,
.container-fluid:before,
.container-fluid:after,
.row:before,
.row:after {content:" ";display:table}
.clearfix:after,
.container:after,
.container-fluid:after,
.row:after {clear:both}
.center-block {display:block;margin-left:auto;margin-right:auto}
.pull-right {float:right !important}
.pull-left {float:left !important}
.hide {display:none !important}
.show {display:block !important}
.invisible {visibility:hidden}
.text-hide {font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}
.hidden {display:none !important;visibility:hidden !important}
.affix {position:fixed}
@-ms-viewport {width:device-width}
.visible-xs,
.visible-sm,
.visible-md,
.visible-lg {display:none !important}
@media (max-width:767px) {.visible-xs {display:block !important }table.visible-xs {display:table }tr.visible-xs {display:table-row !important }th.visible-xs,td.visible-xs {display:table-cell !important }}
@media (min-width:768px) and (max-width:991px) {.visible-sm {display:block !important }table.visible-sm {display:table }tr.visible-sm {display:table-row !important }th.visible-sm,td.visible-sm {display:table-cell !important }}
@media (min-width:992px) and (max-width:1199px) {.visible-md {display:block !important }table.visible-md {display:table }tr.visible-md {display:table-row !important }th.visible-md,td.visible-md {display:table-cell !important }}
@media (min-width:1200px) {.visible-lg {display:block !important }table.visible-lg {display:table }tr.visible-lg {display:table-row !important }th.visible-lg,td.visible-lg {display:table-cell !important }}
@media (max-width:767px) {.hidden-xs {display:none !important }}
@media (min-width:768px) and (max-width:991px) {.hidden-sm {display:none !important }}
@media (min-width:992px) and (max-width:1199px) {.hidden-md {display:none !important }}
@media (min-width:1200px) {.hidden-lg {display:none !important }}
.visible-print {display:none !important}
@media print {.visible-print {display:block !important }table.visible-print {display:table }tr.visible-print {display:table-row !important }th.visible-print,td.visible-print {display:table-cell !important }}
@media print {.hidden-print {display:none !important }}
h1,
h2,
h3,
h4,
h5,
h6,
.h1,
.h2,
.h3,
.h4,
.h5,
.h6 {font-family:inherit;font-weight:400;line-height:1.1;color:inherit}
h1 small,
h2 small,
h3 small,
h4 small,
h5 small,
h6 small,
.h1 small,
.h2 small,
.h3 small,
.h4 small,
.h5 small,
.h6 small,
h1 .small,
h2 .small,
h3 .small,
h4 .small,
h5 .small,
h6 .small,
.h1 .small,
.h2 .small,
.h3 .small,
.h4 .small,
.h5 .small,
.h6 .small {font-weight:normal;line-height:1;color:#999}
h1,
.h1,
h2,
.h2,
h3,
.h3 {margin-top:20px;margin-bottom:10px}
h1 small,
.h1 small,
h2 small,
.h2 small,
h3 small,
.h3 small,
h1 .small,
.h1 .small,
h2 .small,
.h2 .small,
h3 .small,
.h3 .small {font-size:65%}
h4,
.h4,
h5,
.h5,
h6,
.h6 {margin-top:10px;margin-bottom:10px}
h4 small,
.h4 small,
h5 small,
.h5 small,
h6 small,
.h6 small,
h4 .small,
.h4 .small,
h5 .small,
.h5 .small,
h6 .small,
.h6 .small {font-size:75%}
h1,
.h1 {font-size:36px}
h2,
.h2 {font-size:30px}
h3,
.h3 {font-size:24px}
h4,
.h4 {font-size:18px}
h5,
.h5 {font-size:14px}
h6,
.h6 {font-size:12px}
p {margin:0 0 10px}
.lead {margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}
@media (min-width:768px) {.lead {font-size:21px }}
small,
.small {font-size:85%}
cite {font-style:normal}
.text-left {text-align:left}
.text-right {text-align:right}
.text-center {text-align:center}
.text-justify {text-align:justify}
.text-muted {color:#999}
.text-primary {color:#34495e}
a.text-primary:hover {color:#222f3d}
.text-success {color:#3c763d}
a.text-success:hover {color:#2b542c}
.text-info {color:#31708f}
a.text-info:hover {color:#245269}
.text-warning {color:#8a6d3b}
a.text-warning:hover {color:#66512c}
.text-danger {color:#a94442}
a.text-danger:hover {color:#843534}
.bg-primary {color:#fff;background-color:#34495e}
a.bg-primary:hover {background-color:#222f3d}
.bg-success {background-color:#dff0d8}
a.bg-success:hover {background-color:#c1e2b3}
.bg-info {background-color:#d9edf7}
a.bg-info:hover {background-color:#afd9ee}
.bg-warning {background-color:#fcf8e3}
a.bg-warning:hover {background-color:#f7ecb5}
.bg-danger {background-color:#f2dede}
a.bg-danger:hover {background-color:#e4b9b9}
.page-header {padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}
ul,
ol {margin-top:0;margin-bottom:10px}
ul ul,
ol ul,
ul ol,
ol ol {margin-bottom:0}
.list-unstyled {padding-left:0;list-style:none}
.list-inline {padding-left:0;list-style:none;margin-left:-5px}
.list-inline >li {display:inline-block;padding-left:5px;padding-right:5px}
dl {margin-top:0;margin-bottom:20px}
dt,
dd {line-height:1.42857143}
dt {font-weight:bold}
dd {margin-left:0}
@media (min-width:768px) {.dl-horizontal dt {float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap }.dl-horizontal dd {margin-left:180px }}
abbr[title],
abbr[data-original-title] {cursor:help;border-bottom:1px dotted #999}
.initialism {font-size:90%;text-transform:uppercase}
blockquote {padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}
blockquote p:last-child,
blockquote ul:last-child,
blockquote ol:last-child {margin-bottom:0}
blockquote footer,
blockquote small,
blockquote .small {display:block;font-size:80%;line-height:1.42857143;color:#999}
blockquote footer:before,
blockquote small:before,
blockquote .small:before {content:'\2014 \00A0'}
.blockquote-reverse,
blockquote.pull-right {padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}
.blockquote-reverse footer:before,
blockquote.pull-right footer:before,
.blockquote-reverse small:before,
blockquote.pull-right small:before,
.blockquote-reverse .small:before,
blockquote.pull-right .small:before {content:''}
.blockquote-reverse footer:after,
blockquote.pull-right footer:after,
.blockquote-reverse small:after,
blockquote.pull-right small:after,
.blockquote-reverse .small:after,
blockquote.pull-right .small:after {content:'\00A0 \2014'}
blockquote:before,
blockquote:after {content:""}
address {margin-bottom:20px;font-style:normal;line-height:1.42857143}
.oc-icon-chain:before,
.icon-chain:before,
.oc-icon-chain-broken:before,
.icon-chain-broken:before {content:"\f127"}
.close {float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;font-family:sans-serif;opacity:0.2;filter:alpha(opacity=20)}
.close:hover,
.close:focus {color:#000;text-decoration:none;cursor:pointer;opacity:0.5;filter:alpha(opacity=50)}
button.close {padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}
@font-face {font-family:'FontAwesome';src:url('../library/font-awesome-4.7.0/fonts/fontawesome-webfont.eot?v=1.0.1');src:url('../library/font-awesome-4.7.0/fonts/fontawesome-webfont.eot?#iefix&v=1.0.1') format('embedded-opentype'),url('../library/font-awesome-4.7.0/fonts/fontawesome-webfont.woff?v=1.0.1') format('woff'),url('../ui/font/fontawesome-webfont.ttf?v=1.0.1') format('truetype'),url('../library/font-awesome-4.7.0/fonts/fontawesome-webfont.svg#fontawesomeregular?v=1.0.1') format('svg');font-weight:normal;font-style:normal}
[class^="icon-"],
[class*=" icon-"] {font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;display:inline;width:auto;height:auto;line-height:normal;vertical-align:baseline;background-image:none;background-position:0% 0%;background-repeat:repeat;margin-top:0}
[class^="icon-"]:before,
[class*=" icon-"]:before {text-decoration:inherit;display:inline-block;speak:none}
[class^="icon-"].pull-left,
[class*=" icon-"].pull-left {margin-right:.3em}
[class^="icon-"].pull-right,
[class*=" icon-"].pull-right {margin-left:.3em}
[class^="oc-icon-"]:before,
[class*=" oc-icon-"]:before {display:inline-block;margin-right:8px;font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;vertical-align:baseline}
[class^="oc-icon-"].empty:before,
[class*=" oc-icon-"].empty:before {margin-right:0}
.icon-lg {font-size:1.33333333em;line-height:0.75em;vertical-align:-15%}
.icon-2x {font-size:2em}
.icon-3x {font-size:3em}
.icon-4x {font-size:4em}
.icon-5x {font-size:5em}
body {padding-top:20px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";background:#f3f3f3;color:#405261}
h1,
h2,
h3,
h4,
h5 {font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";text-transform:uppercase}
h1 {font-weight:300;font-size:50px;margin-bottom:15px}
h1 i[class^="icon-"]:before {font-size:46px}
i[class^="icon-"].warning {color:#c84530}
h3 {font-size:24px;font-weight:300}
p.lead {font-size:16px;font-weight:300}
</style>
</head>
<body>
<div class="container">
<h1><i class="icon-chain-broken warning"></i> Page not found</h1>
<p class="lead">The requested page cannot be found.</p>
</div>
</body>
</html>