-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
314 lines (276 loc) · 13.6 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
<!doctype html>
<html lang="pt">
<!-- HEAD -->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="Attempt connection and print">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<title>IMPRIMIR BASICO</title>
<!-- URL PARSER -->
<!-- Esta función recibe el contenido enviado desde el sportsbook en formato codificado URI
para luego usarlas para decodificarlas y codificarlas en utf-8 para mandarlas a la función de impresión.
En este caso se usa el contenido de la variable mytext. -->
<script>
function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
vars[key] = value;
});
return vars;
};
var number = getUrlVars()["x"];
var mytext = getUrlVars()["text"];
</script>
<!-- END OF URL PARSER -->
<!-- Polymer components -->
<script src="bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="bower_components/paper-progress/paper-progress.html">
<link rel="import" href="bower_components/paper-slider/paper-slider.html">
<link rel="import" href="bower_components/paper-button/paper-button.html">
<link rel="import" href="bower_components/paper-card/paper-card.html">
<link rel="import" href="bower_components/paper-dialog/paper-dialog.html">
<link rel="import" href="bower_components/paper-input/paper-input.html">
<link rel="import" href="bower_components/paper-input/paper-input-container.html">
<link rel="import" href="bower_components/paper-input/paper-input-error.html">
<link rel="import" href="bower_components/paper-input/paper-input-char-counter.html">
<link rel="import" href="bower_components/paper-input/paper-textarea.html">
<link rel="import" href="bower_components/paper-styles/color.html">
<link rel="stylesheet" href="bower_components/paper-styles/demo.css">
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<!-- CSS STYLE -->
<!-- END OF CSS STYLE -->
</head>
<!-- END OF HEAD -->
<!-- BODY -->
<body unresolved>
<!-- ESTE ES EL BOTON QUE SE LLAMARA printButton y tendrá un event listener que inicia el proceso -->
<button id="print">IMPRIMIR</button>
<!-- ESTE DIALOGO APARECE CUANDO HAY UN ERROR -->
<paper-dialog id="dialog">
<h2>Erro</h2>
<p>A impresora não está online</p>
<a href="https://vibeordie.github.io/print" target="_blank" ><p>A impresora deve estar conectada<BR>com essa ferramenta</p></a>
</paper-dialog>
<br>
<br>
<br>
<!-- ESTE ES EL ELEMENTO QUE ALMACENARÁ LA IMAGEN CON EL LOGO -->
<paper-card id="logo" style='display:none;'>
<div class="card-content" style='display:none;'>
<image id="image" src="logoballs2.png" width="200px" style='display:none;'></image>
</div>
</paper-card>
<!-- ESTE ES EL ELEMENTO DONDE SE COLOCARÁ EL TEXTO DEL URLPARSER DECODIFICADO Y DEL QUE SE CODIFICARA A UTF -->
<paper-card hidden>
<div class="card-content">
<p id="message" label="O ticket não foi importado do site"></p>
</div>
</paper-card>
<!-- SCRIPTS -->
<!-- BLUETOOTH SCRIPT -->
<script>
// decodificamos el valor de mytext que había sido recibido por URL PARSER en el HEAD
document.getElementById("message").innerHTML = decodeURIComponent(mytext).replace(/\+/g, " ");
'use strict';
// Escuchamos a un evento que informa que todos los webcomponents fueron cargados
document.addEventListener('WebComponentsReady', function() {
// Asignamos una variable para el objeto dialog que aparecerá si hay algún error.
let dialog = document.querySelector('#dialog');
// Asignamos una variable para message que será el componente que recibirá y mostrará el texto
let message = document.querySelector('#message');
// Asignamos una variable para el componente del botón imprimir de polymer elements
let printButton = document.querySelector('#print');
// Declaramos la existencia de printCharacteristic que almacerá la caracteristica bluetooth de impresión
let printCharacteristic;
// Declaramos que la variable index que usaremos para ordenar los bytes de a 20 en el proceso de encolado
let index = 0;
// Declaramos una variable data que contendrá el contenido de la información a dividir en chunks
let data;
// Declaramos una variable que contendrá la información del texto a dividir en chunks
let textdata;
// Declaramos una variable textindex para ordernar los chunks a dividir por la función de impresión txt
let textindex = 0;
// Asignamos una variable image al componente polymer image
let image = document.querySelector('#image');
// Creamos un elemento llamado canvas en donde pondremos la imagen a imprimir
let canvas = document.createElement('canvas');
// Las dimensiones del Canvas deben ser estas para el tipo de impresora, siempre múltiplos de 40
canvas.width = 360;
canvas.height = 240;
// Definimos un contexto 2D para el canvas
let context = canvas.getContext("2d");
// Dibujamos la imagen del componente image en el canvas
context.drawImage(image, 0, 0, canvas.width, canvas.height);
// Asignamos una variable ImageData que extraerá la información de imagen que está en el context del canvas
let imageData = context.getImageData(0, 0, canvas.width, canvas.height).data;
//
// Función para pasar a blanco y negro la imagen
function getDarkPixel(x, y) {
// Devolver los pixeles que deban imprimirse negros
let red = imageData[((canvas.width * y) + x) * 4];
let green = imageData[((canvas.width * y) + x) * 4 + 1];
let blue = imageData[((canvas.width * y) + x) * 4 + 2];
return (red + green + blue) > 0 ? 1 : 0;
}
// Función para obtener la información de imagen lista para impresión
function getImagePrintData() {
// Verificamos que se haya podido obtener correctamente la imagen del context
if (imageData == null) {
console.log('No hay imagen para imprimir!');
return new Uint8Array([]);
}
// Cada fila es representada por 8 pixels en una fila
let printData = new Uint8Array(canvas.width / 8 * canvas.height + 8);
// Crear los header bytes para imprimir la imagen
let offset = 0;
printData[0] = 29; // Print raster bitmap
printData[1] = 118; // Print raster bitmap
printData[2] = 48; // Print raster bitmap
printData[3] = 0; // Normal 203.2 DPI
printData[4] = canvas.width / 8; // Number of horizontal data bits (LSB)
printData[5] = 0; // Number of horizontal data bits (MSB)
printData[6] = canvas.height % 256; // Number of vertical data bits (LSB)
printData[7] = canvas.height / 256; // Number of vertical data bits (MSB)
offset = 7;
// Loop en las filas de la imagen en bytes
for (let i = 0; i < canvas.height; ++i) {
for (let k = 0; k < canvas.width / 8; ++k) {
let k8 = k * 8;
// Mapeo posicional de pixel a bit
printData[++offset] = getDarkPixel(k8 + 0, i) * 128 + getDarkPixel(k8 + 1, i) * 64 +
getDarkPixel(k8 + 2, i) * 32 + getDarkPixel(k8 + 3, i) * 16 +
getDarkPixel(k8 + 4, i) * 8 + getDarkPixel(k8 + 5, i) * 4 +
getDarkPixel(k8 + 6, i) * 2 + getDarkPixel(k8 + 7, i);
}
}
// Devuelve un objeto en blanco y negro de la imagen
return printData;
}
// Función para manejo de errores
function handleError(error) {
console.log(error);
// Si hay error entonces la caracteristica de bluetooth se resetea
printCharacteristic = null;
// Abre el webcomponent Dialog para informar el mensaje de error
dialog.open();
}
// Manda en bloques de 20 bytes a la impresora el contenido de la imagen procesada a blanco y negro
function sendNextImageDataBatch(resolve, reject) {
if (index + 20 < data.length) {
printCharacteristic.writeValue(data.slice(index, index + 20)).then(() => {
index += 20;
sendNextImageDataBatch(resolve, reject);
})
.catch(error => reject(error));
} else {
// Send the last bytes
if (index < data.length) {
printCharacteristic.writeValue(data.slice(index, data.length)).then(() => {
resolve();
})
.catch(error => reject(error));
} else {
resolve();
}
}
}
// Manda en bloques de 20 bytes directo a la impresora el contenido del texto a imprimir directo
function sendNextTextDataBatch(resolve, reject) {
if (textindex + 20 < textdata.length) {
// Utilizamos el método writeValue de la caracteristica de impresión y le pasamos un slice de
// textdata dividido en 20 bytes
printCharacteristic.writeValue(textdata.slice(textindex, textindex + 20)).then(() => {
// pasar a los siguientes 20 bytes
textindex += 20;
sendNextTextDataBatch(resolve, reject);
})
.catch(error => reject(error));
} else {
// Manda los últimos bytes si son menos que 20
if (textindex < textdata.length) {
// Utiliza el writevalue de la caracteristica para dividir en slices lo restante y enviarlo
printCharacteristic.writeValue(textdata.slice(textindex, textdata.length)).then(() => {
resolve();
})
.catch(error => reject(error));
} else {
resolve();
}
}
}
// Inicia el proceso de Impresión de imagen (getImagePrintData obtiene la imagen en ByN y la pasa x encolador)
function sendImageData() {
index = 0;
data = getImagePrintData();
return new Promise(function(resolve, reject) {
sendNextImageDataBatch(resolve, reject);
});
}
// Inicia el proceso de Impresión de texto ( Decodificar el URI enviado x URLPARSER
// y lo codifica a UTF-8 para asignarlo como contenido del webcomponent message y luego enviarlo al encolador)
function sendTextData() {
textindex = 0;
// Creamos un objecto encoder de utf-8
let encoder = new TextEncoder("utf-8");
// Aquí asignamos el valor del webcomponent message para que sea el valor decodificado del URI pasado x urlparser
message.value = decodeURIComponent(mytext).replace(/\+/g, " ");
// Agregamos al final un espacio y unos puntos para que se note el fin del ticket y donde debe ser cortado
message.value += " ................. ";
// Codificamos el mensaje a UTF para enviarlo al encolador(sendNextTextDataBatch) a ser partido e impreso
textdata = encoder.encode(message.value + '\u000A\u000D');
//Encolar
return new Promise(function(resolve, reject) {
sendNextTextDataBatch(resolve, reject);
});
}
// Esta función ejecuta la función de impresión de imagen primero y luego la de texto
function sendPrinterData() {
// Imprime Imagen primero
sendImageData()
// Imprime Texto Despues
.then(sendTextData)
// atrapa cualquier error y lo manda a handleError
.catch(handleError);
}
// Creamos una función que escucha clicks del elemento printButton que
// hemos asociado anteriormente al web component button
printButton.addEventListener('click', function () {
// En caso que aun no esté conectada la impresora o no haya una característica para usar en el cache
if (printCharacteristic == null) {
// Que el browser abra una ventanda pidiendo indicar un dispositivo
navigator.bluetooth.requestDevice({
filters: [{
// pero que muestra únicamente los que poseen este uuuid
services: ['000018f0-0000-1000-8000-00805f9b34fb']
}]
})
.then(device => {
// Entonces tendremos un objeto device y conectaremos a su servidor GATT
return device.gatt.connect();
})
// Entonces habrá un servidor GATT al que podemos pedirle un servicio
.then(server => server.getPrimaryService("000018f0-0000-1000-8000-00805f9b34fb"))
// A ese servicio podremos solicitarle una característica y esta es la de imprimir
.then(service => service.getCharacteristic("00002af1-0000-1000-8000-00805f9b34fb"))
.then(characteristic => {
// si hay una caracteristica, almacenarla como tal
printCharacteristic = characteristic;
// y comenzar a imprimir
sendPrinterData();
})
// Atrapar cualquier error y ejecutar handleError en ese caso
.catch(handleError);
} else {
// Si ya hemos imprimido una vez, podemos imprimir de nuevo sin pedir la característica
sendPrinterData();
}
}); // Fin función printButton
});// Fin del Event Listener de WebComponentsReady
</script>
<!-- END BLUETOOTH SCRIPT -->
</body>
<!-- THIS IS THE END OF THE BODY -->
</html>