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
+27
View File
@@ -0,0 +1,27 @@
# JSPrintManager
## Advanced Client-side Printing Solution for Javascript
**[JSPrintManager](https://neodynamic.com/products/printing/js-print-manager)** is a **Javascript + Client App** solution for **Client-side Printing** scenarios **designed to be used in any Website** developed on top of **any Web Platform like ASP.NET, PHP, Django, Ruby On Rails (RoR), Express.js and more!**
By writing pure Javascript code, **JSPrintManager** allows you to _easily send raw data, text and native commands_ as well as _known file formats (like PDF, TXT, DOC, XLS, JPG, PNG)_ to any printer installed or available at the client machine *without showing or displaying any print dialog box!*
**[More details about JSPrintManager...](https://neodynamic.com/products/printing/js-print-manager)**
## JSPrintManager Components
- **The Website component (JSPrintManager.js)** is a Javascript object which is used in a website to generate _"Client Print Jobs"_.
- **The Client-side component** is a lightweight native app (without any dependencies) that processes all the _"Client Print Jobs"_ generated by the Javascript object. **JSPrintManager App** can be installed on **Windows, Linux, Mac & Raspberry Pi!** **[Download JSPrintManager App...](https://neodynamic.com/downloads/jspm)**
## Sample Code
This GitHub repo contains the source code of [JSPrintManager Online Demo Website](https://jsprintmanager.azurewebsites.net)
## Licensing
**JSPrintManager is a Commercial** product. Licensing model and prices are available [here](https://neodynamic.com/products/printing/js-print-manager/buy)
## Support
Tech questions are handled by [Neodynamic Dev Team](https://neodynamic/support)
+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>
+416
View File
@@ -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>
Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

+233
View File
@@ -0,0 +1,233 @@
declare namespace JSPM {
class ClientPrintJob {
private _clientPrinter;
clientPrinter: IClientPrinter;
private _printerCommandsCopies;
printerCommandsCopies: number;
private _printerCommands;
printerCommands: string;
private _binaryPrinterCommands;
binaryPrinterCommands: Uint8Array;
private _printFileGroup;
readonly files: PrintFile[];
sendToClient(): Promise<{}>;
_intToByteArray(number: number): Uint8Array;
_genPFGArrayAsync(printFileGroup: PrintFile[]): Promise<Blob>;
_genPCArrayAsync(printerCommands: string, binPrinterCommands: Uint8Array, printerCopies: number): Promise<Blob>;
_str2UTF8Array(str: string): number[];
_genPrinterArrayAsync(clientPrinter: IClientPrinter): Promise<Uint8Array>;
_generateDataAsync(): Promise<Blob>;
}
}
declare namespace JSPM {
class ClientPrintJobGroup {
_jobs: ClientPrintJob[];
readonly jobs: ClientPrintJob[];
sendToClient(): Promise<{}>;
private _generateMiniJob(cj);
private _generateDataAsync();
private _intToArray(number);
}
}
declare namespace JSPM {
interface IClientPrinter {
Id: any;
serialize(): any;
}
class DefaultPrinter implements IClientPrinter {
Id: string;
serialize(): string;
}
class InstalledPrinter implements IClientPrinter {
Id: string;
private _name;
private _printDefault;
private _tray;
private _paper;
private bool2str(value, true_val?, false_val?);
printerName: string;
printToDefaultIfNotFound: boolean;
trayName: string;
paperName: string;
constructor(printerName: string, printToDefaultIfNotFound?: boolean, trayName?: string, paperName?: string);
serialize(): string;
}
class ParallelPortPrinter implements IClientPrinter {
Id: string;
private _parallelPortName;
portName: string;
constructor(portName: string);
serialize(): string;
}
class SerialPortPrinter implements IClientPrinter {
Id: string;
private _serialPortName;
private _serialPortBaudRate;
private _serialPortParity;
private _serialPortStopBits;
private _serialPortDataBits;
private _serialPortFlowControl;
portName: string;
baudRate: number;
parity: Serial.Parity;
stopBits: Serial.StopBits;
dataBits: number;
flowControl: Serial.Handshake;
constructor(portName: string, baudRate: number, parity: Serial.Parity, stopBits: Serial.StopBits, dataBits: number, flowControl: Serial.Handshake);
serialize(): string;
}
class NetworkPrinter implements IClientPrinter {
Id: number;
private _networkIPAddress;
private _networkPort;
private _dnsName;
dnsName: string;
ipAddress: string;
port: number;
constructor(port: number, ipAddress?: string, dnsName?: string);
serialize(): string;
}
class UserSelectedPrinter implements IClientPrinter {
Id: string;
serialize(): string;
}
}
declare namespace JSPM {
enum FileSourceType {
Base64 = 0,
Text = 1,
BLOB = 2,
URL = 3,
}
enum WSStatus {
Open = 0,
Closed = 1,
BlackListed = 2,
WaitingForUserResponse = 3,
}
enum PrintRotation {
None = 3,
Rot90 = 5,
Rot180 = 6,
Rot270 = 4,
}
enum TextAlignment {
Left = 0,
Center = 1,
Right = 2,
Justify = 3,
}
enum PrintOrientation {
Portrait = 0,
Landscape = 1,
}
}
declare namespace JSPM.Serial {
enum Parity {
None = 0,
Odd = 1,
Even = 2,
Mark = 3,
Space = 4,
}
enum StopBits {
None = 0,
One = 1,
Two = 2,
OnePointFive = 3,
}
enum Handshake {
None = 0,
RequestToSend = 1,
RequestToSendXOnXOff = 2,
XOnXOff = 3,
}
}
declare namespace JSPM {
class JSPMWebSocket {
private _ws;
private _addr;
private _port;
private _secure;
private _status;
private _job_list;
readonly address: string;
readonly port: number;
readonly isSecure: boolean;
readonly status: WSStatus;
autoReconnect: boolean;
onClose: (e: any) => void;
onOpen: (e: any) => void;
onStatusChanged: () => void;
constructor(addr?: string, port?: number, secure?: boolean, auto_reconnect?: boolean);
private _onOpen(e, __this);
private _onMessage(e, job_list);
private _onError(e);
private _pingPong();
private _onClose(e, __this);
private _genID();
private _send(data, ok, err);
start(): Promise<void>;
send(data: any): Promise<any>;
stop(): void;
}
}
declare namespace JSPM {
class JSPrintManager {
static WS: JSPMWebSocket;
static auto_reconnect: boolean;
static start(secure?: boolean, host?: string, port?: number): Promise<void>;
static getPrinters(): Promise<{}>;
static getPrintersInfo(): Promise<{}>;
static readonly websocket_status: WSStatus;
static showAbout(): Promise<any>;
static updateClient(): Promise<any>;
static stop(): void;
}
}
declare namespace JSPM {
class PrintFile {
fileContentType: FileSourceType;
fileContent: any;
fileName: string;
private _copies;
copies: number;
private escapeInvalidFileNameChars();
constructor(fileContent: any, fileContentType: FileSourceType, fileName: string, copies?: number);
protected bool2str(value: any, true_val?: string, false_val?: string): string;
serialize(): Promise<zip.Reader>;
}
}
declare namespace JSPM {
class PrintFilePDF extends PrintFile {
printAsGrayscale: boolean;
printAnnotations: boolean;
printRange: string;
printInReverseOrder: boolean;
printRotation: PrintRotation;
constructor(fileContent: any, fileContentType: FileSourceType, fileName: string, copies?: number);
isValidRange(range: string): boolean;
private getBLOBContent();
serialize(): Promise<zip.Reader>;
}
}
declare namespace JSPM {
class PrintFileTXT extends PrintFile {
textContent: string;
textAligment: TextAlignment;
fontName: string;
fontBold: boolean;
fontItalic: boolean;
fontUnderline: boolean;
fontStrikethrough: boolean;
fontSize: number;
fontColor: string;
printOrientation: PrintOrientation;
marginLeft: number;
marginRight: number;
marginTop: number;
marginBottom: number;
constructor(fileContent: string, fileName: string, copies?: number);
serialize(): Promise<zip.Reader>;
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+416
View File
@@ -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>
+254
View File
@@ -0,0 +1,254 @@
/*
Copyright (c) 2013 Gildas Lormeau. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
(function() {
"use strict";
var ERR_HTTP_RANGE = "HTTP Range not supported.";
var Reader = zip.Reader;
var Writer = zip.Writer;
var ZipDirectoryEntry;
var appendABViewSupported;
try {
appendABViewSupported = new Blob([ new DataView(new ArrayBuffer(0)) ]).size === 0;
} catch (e) {
}
function isHttpFamily(url) {
var a = document.createElement("a");
a.href = url;
return a.protocol === "http:" || a.protocol === "https:";
}
function HttpReader(url) {
var that = this;
function getData(callback, onerror) {
var request;
if (!that.data) {
request = new XMLHttpRequest();
request.addEventListener("load", function() {
if (!that.size)
that.size = Number(request.getResponseHeader("Content-Length")) || Number(request.response.byteLength);
that.data = new Uint8Array(request.response);
callback();
}, false);
request.addEventListener("error", onerror, false);
request.open("GET", url);
request.responseType = "arraybuffer";
request.send();
} else
callback();
}
function init(callback, onerror) {
if (!isHttpFamily(url)) {
// For schemas other than http(s), HTTP HEAD may be unavailable,
// so use HTTP GET instead.
getData(callback, onerror);
return;
}
var request = new XMLHttpRequest();
request.addEventListener("load", function() {
that.size = Number(request.getResponseHeader("Content-Length"));
// If response header doesn't return size then prefetch the content.
if (!that.size) {
getData(callback, onerror);
} else {
callback();
}
}, false);
request.addEventListener("error", onerror, false);
request.open("HEAD", url);
request.send();
}
function readUint8Array(index, length, callback, onerror) {
getData(function() {
callback(new Uint8Array(that.data.subarray(index, index + length)));
}, onerror);
}
that.size = 0;
that.init = init;
that.readUint8Array = readUint8Array;
}
HttpReader.prototype = new Reader();
HttpReader.prototype.constructor = HttpReader;
function HttpRangeReader(url) {
var that = this;
function init(callback, onerror) {
var request = new XMLHttpRequest();
request.addEventListener("load", function() {
that.size = Number(request.getResponseHeader("Content-Length"));
if (request.getResponseHeader("Accept-Ranges") == "bytes")
callback();
else
onerror(ERR_HTTP_RANGE);
}, false);
request.addEventListener("error", onerror, false);
request.open("HEAD", url);
request.send();
}
function readArrayBuffer(index, length, callback, onerror) {
var request = new XMLHttpRequest();
request.open("GET", url);
request.responseType = "arraybuffer";
request.setRequestHeader("Range", "bytes=" + index + "-" + (index + length - 1));
request.addEventListener("load", function() {
callback(request.response);
}, false);
request.addEventListener("error", onerror, false);
request.send();
}
function readUint8Array(index, length, callback, onerror) {
readArrayBuffer(index, length, function(arraybuffer) {
callback(new Uint8Array(arraybuffer));
}, onerror);
}
that.size = 0;
that.init = init;
that.readUint8Array = readUint8Array;
}
HttpRangeReader.prototype = new Reader();
HttpRangeReader.prototype.constructor = HttpRangeReader;
function ArrayBufferReader(arrayBuffer) {
var that = this;
function init(callback, onerror) {
that.size = arrayBuffer.byteLength;
callback();
}
function readUint8Array(index, length, callback, onerror) {
callback(new Uint8Array(arrayBuffer.slice(index, index + length)));
}
that.size = 0;
that.init = init;
that.readUint8Array = readUint8Array;
}
ArrayBufferReader.prototype = new Reader();
ArrayBufferReader.prototype.constructor = ArrayBufferReader;
function ArrayBufferWriter() {
var array, that = this;
function init(callback, onerror) {
array = new Uint8Array();
callback();
}
function writeUint8Array(arr, callback, onerror) {
var tmpArray = new Uint8Array(array.length + arr.length);
tmpArray.set(array);
tmpArray.set(arr, array.length);
array = tmpArray;
callback();
}
function getData(callback) {
callback(array.buffer);
}
that.init = init;
that.writeUint8Array = writeUint8Array;
that.getData = getData;
}
ArrayBufferWriter.prototype = new Writer();
ArrayBufferWriter.prototype.constructor = ArrayBufferWriter;
function FileWriter(fileEntry, contentType) {
var writer, that = this;
function init(callback, onerror) {
fileEntry.createWriter(function(fileWriter) {
writer = fileWriter;
callback();
}, onerror);
}
function writeUint8Array(array, callback, onerror) {
var blob = new Blob([ appendABViewSupported ? array : array.buffer ], {
type : contentType
});
writer.onwrite = function() {
writer.onwrite = null;
callback();
};
writer.onerror = onerror;
writer.write(blob);
}
function getData(callback) {
fileEntry.file(callback);
}
that.init = init;
that.writeUint8Array = writeUint8Array;
that.getData = getData;
}
FileWriter.prototype = new Writer();
FileWriter.prototype.constructor = FileWriter;
zip.FileWriter = FileWriter;
zip.HttpReader = HttpReader;
zip.HttpRangeReader = HttpRangeReader;
zip.ArrayBufferReader = ArrayBufferReader;
zip.ArrayBufferWriter = ArrayBufferWriter;
if (zip.fs) {
ZipDirectoryEntry = zip.fs.ZipDirectoryEntry;
ZipDirectoryEntry.prototype.addHttpContent = function(name, URL, useRangeHeader) {
function addChild(parent, name, params, directory) {
if (parent.directory)
return directory ? new ZipDirectoryEntry(parent.fs, name, params, parent) : new zip.fs.ZipFileEntry(parent.fs, name, params, parent);
else
throw "Parent entry is not a directory.";
}
return addChild(this, name, {
data : URL,
Reader : useRangeHeader ? HttpRangeReader : HttpReader
});
};
ZipDirectoryEntry.prototype.importHttpContent = function(URL, useRangeHeader, onend, onerror) {
this.importZip(useRangeHeader ? new HttpRangeReader(URL) : new HttpReader(URL), onend, onerror);
};
zip.fs.FS.prototype.importHttpContent = function(URL, useRangeHeader, onend, onerror) {
this.entries = [];
this.root = new ZipDirectoryEntry(this);
this.root.importHttpContent(URL, useRangeHeader, onend, onerror);
};
}
})();
+961
View File
@@ -0,0 +1,961 @@
/*
Copyright (c) 2013 Gildas Lormeau. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
(function(obj) {
"use strict";
var ERR_BAD_FORMAT = "File format is not recognized.";
var ERR_CRC = "CRC failed.";
var ERR_ENCRYPTED = "File contains encrypted entry.";
var ERR_ZIP64 = "File is using Zip64 (4gb+ file size).";
var ERR_READ = "Error while reading zip file.";
var ERR_WRITE = "Error while writing zip file.";
var ERR_WRITE_DATA = "Error while writing file data.";
var ERR_READ_DATA = "Error while reading file data.";
var ERR_DUPLICATED_NAME = "File already exists.";
var CHUNK_SIZE = 512 * 1024;
var TEXT_PLAIN = "text/plain";
var appendABViewSupported;
try {
appendABViewSupported = new Blob([ new DataView(new ArrayBuffer(0)) ]).size === 0;
} catch (e) {
}
function Crc32() {
this.crc = -1;
}
Crc32.prototype.append = function append(data) {
var crc = this.crc | 0, table = this.table;
for (var offset = 0, len = data.length | 0; offset < len; offset++)
crc = (crc >>> 8) ^ table[(crc ^ data[offset]) & 0xFF];
this.crc = crc;
};
Crc32.prototype.get = function get() {
return ~this.crc;
};
Crc32.prototype.table = (function() {
var i, j, t, table = []; // Uint32Array is actually slower than []
for (i = 0; i < 256; i++) {
t = i;
for (j = 0; j < 8; j++)
if (t & 1)
t = (t >>> 1) ^ 0xEDB88320;
else
t = t >>> 1;
table[i] = t;
}
return table;
})();
// "no-op" codec
function NOOP() {}
NOOP.prototype.append = function append(bytes, onprogress) {
return bytes;
};
NOOP.prototype.flush = function flush() {};
function blobSlice(blob, index, length) {
if (index < 0 || length < 0 || index + length > blob.size)
throw new RangeError('offset:' + index + ', length:' + length + ', size:' + blob.size);
if (blob.slice)
return blob.slice(index, index + length);
else if (blob.webkitSlice)
return blob.webkitSlice(index, index + length);
else if (blob.mozSlice)
return blob.mozSlice(index, index + length);
else if (blob.msSlice)
return blob.msSlice(index, index + length);
}
function getDataHelper(byteLength, bytes) {
var dataBuffer, dataArray;
dataBuffer = new ArrayBuffer(byteLength);
dataArray = new Uint8Array(dataBuffer);
if (bytes)
dataArray.set(bytes, 0);
return {
buffer : dataBuffer,
array : dataArray,
view : new DataView(dataBuffer)
};
}
// Readers
function Reader() {
}
function TextReader(text) {
var that = this, blobReader;
function init(callback, onerror) {
var blob = new Blob([ text ], {
type : TEXT_PLAIN
});
blobReader = new BlobReader(blob);
blobReader.init(function() {
that.size = blobReader.size;
callback();
}, onerror);
}
function readUint8Array(index, length, callback, onerror) {
blobReader.readUint8Array(index, length, callback, onerror);
}
that.size = 0;
that.init = init;
that.readUint8Array = readUint8Array;
}
TextReader.prototype = new Reader();
TextReader.prototype.constructor = TextReader;
function Data64URIReader(dataURI) {
var that = this, dataStart;
function init(callback) {
var dataEnd = dataURI.length;
while (dataURI.charAt(dataEnd - 1) == "=")
dataEnd--;
dataStart = dataURI.indexOf(",") + 1;
that.size = Math.floor((dataEnd - dataStart) * 0.75);
callback();
}
function readUint8Array(index, length, callback) {
var i, data = getDataHelper(length);
var start = Math.floor(index / 3) * 4;
var end = Math.ceil((index + length) / 3) * 4;
var bytes = obj.atob(dataURI.substring(start + dataStart, end + dataStart));
var delta = index - Math.floor(start / 4) * 3;
for (i = delta; i < delta + length; i++)
data.array[i - delta] = bytes.charCodeAt(i);
callback(data.array);
}
that.size = 0;
that.init = init;
that.readUint8Array = readUint8Array;
}
Data64URIReader.prototype = new Reader();
Data64URIReader.prototype.constructor = Data64URIReader;
function BlobReader(blob) {
var that = this;
function init(callback) {
that.size = blob.size;
callback();
}
function readUint8Array(index, length, callback, onerror) {
var reader = new FileReader();
reader.onload = function(e) {
callback(new Uint8Array(e.target.result));
};
reader.onerror = onerror;
try {
reader.readAsArrayBuffer(blobSlice(blob, index, length));
} catch (e) {
onerror(e);
}
}
that.size = 0;
that.init = init;
that.readUint8Array = readUint8Array;
}
BlobReader.prototype = new Reader();
BlobReader.prototype.constructor = BlobReader;
// Writers
function Writer() {
}
Writer.prototype.getData = function(callback) {
callback(this.data);
};
function TextWriter(encoding) {
var that = this, blob;
function init(callback) {
blob = new Blob([], {
type : TEXT_PLAIN
});
callback();
}
function writeUint8Array(array, callback) {
blob = new Blob([ blob, appendABViewSupported ? array : array.buffer ], {
type : TEXT_PLAIN
});
callback();
}
function getData(callback, onerror) {
var reader = new FileReader();
reader.onload = function(e) {
callback(e.target.result);
};
reader.onerror = onerror;
reader.readAsText(blob, encoding);
}
that.init = init;
that.writeUint8Array = writeUint8Array;
that.getData = getData;
}
TextWriter.prototype = new Writer();
TextWriter.prototype.constructor = TextWriter;
function Data64URIWriter(contentType) {
var that = this, data = "", pending = "";
function init(callback) {
data += "data:" + (contentType || "") + ";base64,";
callback();
}
function writeUint8Array(array, callback) {
var i, delta = pending.length, dataString = pending;
pending = "";
for (i = 0; i < (Math.floor((delta + array.length) / 3) * 3) - delta; i++)
dataString += String.fromCharCode(array[i]);
for (; i < array.length; i++)
pending += String.fromCharCode(array[i]);
if (dataString.length > 2)
data += obj.btoa(dataString);
else
pending = dataString;
callback();
}
function getData(callback) {
callback(data + obj.btoa(pending));
}
that.init = init;
that.writeUint8Array = writeUint8Array;
that.getData = getData;
}
Data64URIWriter.prototype = new Writer();
Data64URIWriter.prototype.constructor = Data64URIWriter;
function BlobWriter(contentType) {
var blob, that = this;
function init(callback) {
blob = new Blob([], {
type : contentType
});
callback();
}
function writeUint8Array(array, callback) {
blob = new Blob([ blob, appendABViewSupported ? array : array.buffer ], {
type : contentType
});
callback();
}
function getData(callback) {
callback(blob);
}
that.init = init;
that.writeUint8Array = writeUint8Array;
that.getData = getData;
}
BlobWriter.prototype = new Writer();
BlobWriter.prototype.constructor = BlobWriter;
/**
* inflate/deflate core functions
* @param worker {Worker} web worker for the task.
* @param initialMessage {Object} initial message to be sent to the worker. should contain
* sn(serial number for distinguishing multiple tasks sent to the worker), and codecClass.
* This function may add more properties before sending.
*/
function launchWorkerProcess(worker, initialMessage, reader, writer, offset, size, onprogress, onend, onreaderror, onwriteerror) {
var chunkIndex = 0, index, outputSize, sn = initialMessage.sn, crc;
function onflush() {
worker.removeEventListener('message', onmessage, false);
onend(outputSize, crc);
}
function onmessage(event) {
var message = event.data, data = message.data, err = message.error;
if (err) {
err.toString = function () { return 'Error: ' + this.message; };
onreaderror(err);
return;
}
if (message.sn !== sn)
return;
if (typeof message.codecTime === 'number')
worker.codecTime += message.codecTime; // should be before onflush()
if (typeof message.crcTime === 'number')
worker.crcTime += message.crcTime;
switch (message.type) {
case 'append':
if (data) {
outputSize += data.length;
writer.writeUint8Array(data, function() {
step();
}, onwriteerror);
} else
step();
break;
case 'flush':
crc = message.crc;
if (data) {
outputSize += data.length;
writer.writeUint8Array(data, function() {
onflush();
}, onwriteerror);
} else
onflush();
break;
case 'progress':
if (onprogress)
onprogress(index + message.loaded, size);
break;
case 'importScripts': //no need to handle here
case 'newTask':
case 'echo':
break;
default:
console.warn('zip.js:launchWorkerProcess: unknown message: ', message);
}
}
function step() {
index = chunkIndex * CHUNK_SIZE;
// use `<=` instead of `<`, because `size` may be 0.
if (index <= size) {
reader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function(array) {
if (onprogress)
onprogress(index, size);
var msg = index === 0 ? initialMessage : {sn : sn};
msg.type = 'append';
msg.data = array;
// posting a message with transferables will fail on IE10
try {
worker.postMessage(msg, [array.buffer]);
} catch(ex) {
worker.postMessage(msg); // retry without transferables
}
chunkIndex++;
}, onreaderror);
} else {
worker.postMessage({
sn: sn,
type: 'flush'
});
}
}
outputSize = 0;
worker.addEventListener('message', onmessage, false);
step();
}
function launchProcess(process, reader, writer, offset, size, crcType, onprogress, onend, onreaderror, onwriteerror) {
var chunkIndex = 0, index, outputSize = 0,
crcInput = crcType === 'input',
crcOutput = crcType === 'output',
crc = new Crc32();
function step() {
var outputData;
index = chunkIndex * CHUNK_SIZE;
if (index < size)
reader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function(inputData) {
var outputData;
try {
outputData = process.append(inputData, function(loaded) {
if (onprogress)
onprogress(index + loaded, size);
});
} catch (e) {
onreaderror(e);
return;
}
if (outputData) {
outputSize += outputData.length;
writer.writeUint8Array(outputData, function() {
chunkIndex++;
setTimeout(step, 1);
}, onwriteerror);
if (crcOutput)
crc.append(outputData);
} else {
chunkIndex++;
setTimeout(step, 1);
}
if (crcInput)
crc.append(inputData);
if (onprogress)
onprogress(index, size);
}, onreaderror);
else {
try {
outputData = process.flush();
} catch (e) {
onreaderror(e);
return;
}
if (outputData) {
if (crcOutput)
crc.append(outputData);
outputSize += outputData.length;
writer.writeUint8Array(outputData, function() {
onend(outputSize, crc.get());
}, onwriteerror);
} else
onend(outputSize, crc.get());
}
}
step();
}
function inflate(worker, sn, reader, writer, offset, size, computeCrc32, onend, onprogress, onreaderror, onwriteerror) {
var crcType = computeCrc32 ? 'output' : 'none';
if (obj.zip.useWebWorkers) {
var initialMessage = {
sn: sn,
codecClass: 'Inflater',
crcType: crcType,
};
launchWorkerProcess(worker, initialMessage, reader, writer, offset, size, onprogress, onend, onreaderror, onwriteerror);
} else
launchProcess(new obj.zip.Inflater(), reader, writer, offset, size, crcType, onprogress, onend, onreaderror, onwriteerror);
}
function deflate(worker, sn, reader, writer, level, onend, onprogress, onreaderror, onwriteerror) {
var crcType = 'input';
if (obj.zip.useWebWorkers) {
var initialMessage = {
sn: sn,
options: {level: level},
codecClass: 'Deflater',
crcType: crcType,
};
launchWorkerProcess(worker, initialMessage, reader, writer, 0, reader.size, onprogress, onend, onreaderror, onwriteerror);
} else
launchProcess(new obj.zip.Deflater(), reader, writer, 0, reader.size, crcType, onprogress, onend, onreaderror, onwriteerror);
}
function copy(worker, sn, reader, writer, offset, size, computeCrc32, onend, onprogress, onreaderror, onwriteerror) {
var crcType = 'input';
if (obj.zip.useWebWorkers && computeCrc32) {
var initialMessage = {
sn: sn,
codecClass: 'NOOP',
crcType: crcType,
};
launchWorkerProcess(worker, initialMessage, reader, writer, offset, size, onprogress, onend, onreaderror, onwriteerror);
} else
launchProcess(new NOOP(), reader, writer, offset, size, crcType, onprogress, onend, onreaderror, onwriteerror);
}
// ZipReader
function decodeASCII(str) {
var i, out = "", charCode, extendedASCII = [ '\u00C7', '\u00FC', '\u00E9', '\u00E2', '\u00E4', '\u00E0', '\u00E5', '\u00E7', '\u00EA', '\u00EB',
'\u00E8', '\u00EF', '\u00EE', '\u00EC', '\u00C4', '\u00C5', '\u00C9', '\u00E6', '\u00C6', '\u00F4', '\u00F6', '\u00F2', '\u00FB', '\u00F9',
'\u00FF', '\u00D6', '\u00DC', '\u00F8', '\u00A3', '\u00D8', '\u00D7', '\u0192', '\u00E1', '\u00ED', '\u00F3', '\u00FA', '\u00F1', '\u00D1',
'\u00AA', '\u00BA', '\u00BF', '\u00AE', '\u00AC', '\u00BD', '\u00BC', '\u00A1', '\u00AB', '\u00BB', '_', '_', '_', '\u00A6', '\u00A6',
'\u00C1', '\u00C2', '\u00C0', '\u00A9', '\u00A6', '\u00A6', '+', '+', '\u00A2', '\u00A5', '+', '+', '-', '-', '+', '-', '+', '\u00E3',
'\u00C3', '+', '+', '-', '-', '\u00A6', '-', '+', '\u00A4', '\u00F0', '\u00D0', '\u00CA', '\u00CB', '\u00C8', 'i', '\u00CD', '\u00CE',
'\u00CF', '+', '+', '_', '_', '\u00A6', '\u00CC', '_', '\u00D3', '\u00DF', '\u00D4', '\u00D2', '\u00F5', '\u00D5', '\u00B5', '\u00FE',
'\u00DE', '\u00DA', '\u00DB', '\u00D9', '\u00FD', '\u00DD', '\u00AF', '\u00B4', '\u00AD', '\u00B1', '_', '\u00BE', '\u00B6', '\u00A7',
'\u00F7', '\u00B8', '\u00B0', '\u00A8', '\u00B7', '\u00B9', '\u00B3', '\u00B2', '_', ' ' ];
for (i = 0; i < str.length; i++) {
charCode = str.charCodeAt(i) & 0xFF;
if (charCode > 127)
out += extendedASCII[charCode - 128];
else
out += String.fromCharCode(charCode);
}
return out;
}
function decodeUTF8(string) {
return decodeURIComponent(escape(string));
}
function getString(bytes) {
var i, str = "";
for (i = 0; i < bytes.length; i++)
str += String.fromCharCode(bytes[i]);
return str;
}
function getDate(timeRaw) {
var date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & 0x0000ffff;
try {
return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5,
(time & 0x001F) * 2, 0);
} catch (e) {
}
}
function readCommonHeader(entry, data, index, centralDirectory, onerror) {
entry.version = data.view.getUint16(index, true);
entry.bitFlag = data.view.getUint16(index + 2, true);
entry.compressionMethod = data.view.getUint16(index + 4, true);
entry.lastModDateRaw = data.view.getUint32(index + 6, true);
entry.lastModDate = getDate(entry.lastModDateRaw);
if ((entry.bitFlag & 0x01) === 0x01) {
onerror(ERR_ENCRYPTED);
return;
}
if (centralDirectory || (entry.bitFlag & 0x0008) != 0x0008) {
entry.crc32 = data.view.getUint32(index + 10, true);
entry.compressedSize = data.view.getUint32(index + 14, true);
entry.uncompressedSize = data.view.getUint32(index + 18, true);
}
if (entry.compressedSize === 0xFFFFFFFF || entry.uncompressedSize === 0xFFFFFFFF) {
onerror(ERR_ZIP64);
return;
}
entry.filenameLength = data.view.getUint16(index + 22, true);
entry.extraFieldLength = data.view.getUint16(index + 24, true);
}
function createZipReader(reader, callback, onerror) {
var inflateSN = 0;
function Entry() {
}
Entry.prototype.getData = function(writer, onend, onprogress, checkCrc32) {
var that = this;
function testCrc32(crc32) {
var dataCrc32 = getDataHelper(4);
dataCrc32.view.setUint32(0, crc32);
return that.crc32 == dataCrc32.view.getUint32(0);
}
function getWriterData(uncompressedSize, crc32) {
if (checkCrc32 && !testCrc32(crc32))
onerror(ERR_CRC);
else
writer.getData(function(data) {
onend(data);
});
}
function onreaderror(err) {
onerror(err || ERR_READ_DATA);
}
function onwriteerror(err) {
onerror(err || ERR_WRITE_DATA);
}
reader.readUint8Array(that.offset, 30, function(bytes) {
var data = getDataHelper(bytes.length, bytes), dataOffset;
if (data.view.getUint32(0) != 0x504b0304) {
onerror(ERR_BAD_FORMAT);
return;
}
readCommonHeader(that, data, 4, false, onerror);
dataOffset = that.offset + 30 + that.filenameLength + that.extraFieldLength;
writer.init(function() {
if (that.compressionMethod === 0)
copy(that._worker, inflateSN++, reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);
else
inflate(that._worker, inflateSN++, reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);
}, onwriteerror);
}, onreaderror);
};
function seekEOCDR(eocdrCallback) {
// "End of central directory record" is the last part of a zip archive, and is at least 22 bytes long.
// Zip file comment is the last part of EOCDR and has max length of 64KB,
// so we only have to search the last 64K + 22 bytes of a archive for EOCDR signature (0x06054b50).
var EOCDR_MIN = 22;
if (reader.size < EOCDR_MIN) {
onerror(ERR_BAD_FORMAT);
return;
}
var ZIP_COMMENT_MAX = 256 * 256, EOCDR_MAX = EOCDR_MIN + ZIP_COMMENT_MAX;
// In most cases, the EOCDR is EOCDR_MIN bytes long
doSeek(EOCDR_MIN, function() {
// If not found, try within EOCDR_MAX bytes
doSeek(Math.min(EOCDR_MAX, reader.size), function() {
onerror(ERR_BAD_FORMAT);
});
});
// seek last length bytes of file for EOCDR
function doSeek(length, eocdrNotFoundCallback) {
reader.readUint8Array(reader.size - length, length, function(bytes) {
for (var i = bytes.length - EOCDR_MIN; i >= 0; i--) {
if (bytes[i] === 0x50 && bytes[i + 1] === 0x4b && bytes[i + 2] === 0x05 && bytes[i + 3] === 0x06) {
eocdrCallback(new DataView(bytes.buffer, i, EOCDR_MIN));
return;
}
}
eocdrNotFoundCallback();
}, function() {
onerror(ERR_READ);
});
}
}
var zipReader = {
getEntries : function(callback) {
var worker = this._worker;
// look for End of central directory record
seekEOCDR(function(dataView) {
var datalength, fileslength;
datalength = dataView.getUint32(16, true);
fileslength = dataView.getUint16(8, true);
if (datalength < 0 || datalength >= reader.size) {
onerror(ERR_BAD_FORMAT);
return;
}
reader.readUint8Array(datalength, reader.size - datalength, function(bytes) {
var i, index = 0, entries = [], entry, filename, comment, data = getDataHelper(bytes.length, bytes);
for (i = 0; i < fileslength; i++) {
entry = new Entry();
entry._worker = worker;
if (data.view.getUint32(index) != 0x504b0102) {
onerror(ERR_BAD_FORMAT);
return;
}
readCommonHeader(entry, data, index + 6, true, onerror);
entry.commentLength = data.view.getUint16(index + 32, true);
entry.directory = ((data.view.getUint8(index + 38) & 0x10) == 0x10);
entry.offset = data.view.getUint32(index + 42, true);
filename = getString(data.array.subarray(index + 46, index + 46 + entry.filenameLength));
entry.filename = ((entry.bitFlag & 0x0800) === 0x0800) ? decodeUTF8(filename) : decodeASCII(filename);
if (!entry.directory && entry.filename.charAt(entry.filename.length - 1) == "/")
entry.directory = true;
comment = getString(data.array.subarray(index + 46 + entry.filenameLength + entry.extraFieldLength, index + 46
+ entry.filenameLength + entry.extraFieldLength + entry.commentLength));
entry.comment = ((entry.bitFlag & 0x0800) === 0x0800) ? decodeUTF8(comment) : decodeASCII(comment);
entries.push(entry);
index += 46 + entry.filenameLength + entry.extraFieldLength + entry.commentLength;
}
callback(entries);
}, function() {
onerror(ERR_READ);
});
});
},
close : function(callback) {
if (this._worker) {
this._worker.terminate();
this._worker = null;
}
if (callback)
callback();
},
_worker: null
};
if (!obj.zip.useWebWorkers)
callback(zipReader);
else {
createWorker('inflater',
function(worker) {
zipReader._worker = worker;
callback(zipReader);
},
function(err) {
onerror(err);
}
);
}
}
// ZipWriter
function encodeUTF8(string) {
return unescape(encodeURIComponent(string));
}
function getBytes(str) {
var i, array = [];
for (i = 0; i < str.length; i++)
array.push(str.charCodeAt(i));
return array;
}
function createZipWriter(writer, callback, onerror, dontDeflate) {
var files = {}, filenames = [], datalength = 0;
var deflateSN = 0;
function onwriteerror(err) {
onerror(err || ERR_WRITE);
}
function onreaderror(err) {
onerror(err || ERR_READ_DATA);
}
var zipWriter = {
add : function(name, reader, onend, onprogress, options) {
var header, filename, date;
var worker = this._worker;
function writeHeader(callback) {
var data;
date = options.lastModDate || new Date();
header = getDataHelper(26);
files[name] = {
headerArray : header.array,
directory : options.directory,
filename : filename,
offset : datalength,
comment : getBytes(encodeUTF8(options.comment || ""))
};
header.view.setUint32(0, 0x14000808);
if (options.version)
header.view.setUint8(0, options.version);
if (!dontDeflate && options.level !== 0 && !options.directory)
header.view.setUint16(4, 0x0800);
header.view.setUint16(6, (((date.getHours() << 6) | date.getMinutes()) << 5) | date.getSeconds() / 2, true);
header.view.setUint16(8, ((((date.getFullYear() - 1980) << 4) | (date.getMonth() + 1)) << 5) | date.getDate(), true);
header.view.setUint16(22, filename.length, true);
data = getDataHelper(30 + filename.length);
data.view.setUint32(0, 0x504b0304);
data.array.set(header.array, 4);
data.array.set(filename, 30);
datalength += data.array.length;
writer.writeUint8Array(data.array, callback, onwriteerror);
}
function writeFooter(compressedLength, crc32) {
var footer = getDataHelper(16);
datalength += compressedLength || 0;
footer.view.setUint32(0, 0x504b0708);
if (typeof crc32 != "undefined") {
header.view.setUint32(10, crc32, true);
footer.view.setUint32(4, crc32, true);
}
if (reader) {
footer.view.setUint32(8, compressedLength, true);
header.view.setUint32(14, compressedLength, true);
footer.view.setUint32(12, reader.size, true);
header.view.setUint32(18, reader.size, true);
}
writer.writeUint8Array(footer.array, function() {
datalength += 16;
onend();
}, onwriteerror);
}
function writeFile() {
options = options || {};
name = name.trim();
if (options.directory && name.charAt(name.length - 1) != "/")
name += "/";
if (files.hasOwnProperty(name)) {
onerror(ERR_DUPLICATED_NAME);
return;
}
filename = getBytes(encodeUTF8(name));
filenames.push(name);
writeHeader(function() {
if (reader)
if (dontDeflate || options.level === 0)
copy(worker, deflateSN++, reader, writer, 0, reader.size, true, writeFooter, onprogress, onreaderror, onwriteerror);
else
deflate(worker, deflateSN++, reader, writer, options.level, writeFooter, onprogress, onreaderror, onwriteerror);
else
writeFooter();
}, onwriteerror);
}
if (reader)
reader.init(writeFile, onreaderror);
else
writeFile();
},
close : function(callback) {
if (this._worker) {
this._worker.terminate();
this._worker = null;
}
var data, length = 0, index = 0, indexFilename, file;
for (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {
file = files[filenames[indexFilename]];
length += 46 + file.filename.length + file.comment.length;
}
data = getDataHelper(length + 22);
for (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {
file = files[filenames[indexFilename]];
data.view.setUint32(index, 0x504b0102);
data.view.setUint16(index + 4, 0x1400);
data.array.set(file.headerArray, index + 6);
data.view.setUint16(index + 32, file.comment.length, true);
if (file.directory)
data.view.setUint8(index + 38, 0x10);
data.view.setUint32(index + 42, file.offset, true);
data.array.set(file.filename, index + 46);
data.array.set(file.comment, index + 46 + file.filename.length);
index += 46 + file.filename.length + file.comment.length;
}
data.view.setUint32(index, 0x504b0506);
data.view.setUint16(index + 8, filenames.length, true);
data.view.setUint16(index + 10, filenames.length, true);
data.view.setUint32(index + 12, length, true);
data.view.setUint32(index + 16, datalength, true);
writer.writeUint8Array(data.array, function() {
writer.getData(callback);
}, onwriteerror);
},
_worker: null
};
if (!obj.zip.useWebWorkers)
callback(zipWriter);
else {
createWorker('deflater',
function(worker) {
zipWriter._worker = worker;
callback(zipWriter);
},
function(err) {
onerror(err);
}
);
}
}
function resolveURLs(urls) {
var a = document.createElement('a');
return urls.map(function(url) {
a.href = url;
return a.href;
});
}
var DEFAULT_WORKER_SCRIPTS = {
deflater: ['z-worker.js', 'deflate.js'],
inflater: ['z-worker.js', 'inflate.js']
};
function createWorker(type, callback, onerror) {
if (obj.zip.workerScripts !== null && obj.zip.workerScriptsPath !== null) {
onerror(new Error('Either zip.workerScripts or zip.workerScriptsPath may be set, not both.'));
return;
}
var scripts;
if (obj.zip.workerScripts) {
scripts = obj.zip.workerScripts[type];
if (!Array.isArray(scripts)) {
onerror(new Error('zip.workerScripts.' + type + ' is not an array!'));
return;
}
scripts = resolveURLs(scripts);
} else {
scripts = DEFAULT_WORKER_SCRIPTS[type].slice(0);
scripts[0] = (obj.zip.workerScriptsPath || '') + scripts[0];
}
var worker = new Worker(scripts[0]);
// record total consumed time by inflater/deflater/crc32 in this worker
worker.codecTime = worker.crcTime = 0;
worker.postMessage({ type: 'importScripts', scripts: scripts.slice(1) });
worker.addEventListener('message', onmessage);
function onmessage(ev) {
var msg = ev.data;
if (msg.error) {
worker.terminate(); // should before onerror(), because onerror() may throw.
onerror(msg.error);
return;
}
if (msg.type === 'importScripts') {
worker.removeEventListener('message', onmessage);
worker.removeEventListener('error', errorHandler);
callback(worker);
}
}
// catch entry script loading error and other unhandled errors
worker.addEventListener('error', errorHandler);
function errorHandler(err) {
worker.terminate();
onerror(err);
}
}
function onerror_default(error) {
console.error(error);
}
obj.zip = {
Reader : Reader,
Writer : Writer,
BlobReader : BlobReader,
Data64URIReader : Data64URIReader,
TextReader : TextReader,
BlobWriter : BlobWriter,
Data64URIWriter : Data64URIWriter,
TextWriter : TextWriter,
createReader : function(reader, callback, onerror) {
onerror = onerror || onerror_default;
reader.init(function() {
createZipReader(reader, callback, onerror);
}, onerror);
},
createWriter : function(writer, callback, onerror, dontDeflate) {
onerror = onerror || onerror_default;
dontDeflate = !!dontDeflate;
writer.init(function() {
createZipWriter(writer, callback, onerror, dontDeflate);
}, onerror);
},
useWebWorkers : true,
/**
* Directory containing the default worker scripts (z-worker.js, deflate.js, and inflate.js), relative to current base url.
* E.g.: zip.workerScripts = './';
*/
workerScriptsPath : null,
/**
* Advanced option to control which scripts are loaded in the Web worker. If this option is specified, then workerScriptsPath must not be set.
* workerScripts.deflater/workerScripts.inflater should be arrays of urls to scripts for deflater/inflater, respectively.
* Scripts in the array are executed in order, and the first one should be z-worker.js, which is used to start the worker.
* All urls are relative to current base url.
* E.g.:
* zip.workerScripts = {
* deflater: ['z-worker.js', 'deflate.js'],
* inflater: ['z-worker.js', 'inflate.js']
* };
*/
workerScripts : null,
};
})(this);