Esta problemática me la planteó un usuario y he hecho un ejemplo que creo puede interesar a otros usuarios de PHPRunner.
El problema surgió con el ejemplo del lector de QR, en el ejemplo siempre se muestra una ventana «amplia» de la cámara y él deseaba que fuera opcional, es decir, que si se deseaba capturar información a través del QR, se pulsase un botón para hacer esta captura y después se siguiese con los datos de entrada del formulario.
Una vez resuelto el caso, se añadió la capacidad de capturado el valor del QR, que el sistema recuperase información en el servidor y cargar los valores recuperados en otros campos del formulario.
Objetivo
- Pasar información de una ventana popup «hija» a la ventana principal «padre», directamente por JavaScript.
- Recogido un valor en un campo, acceder al servidor, recuperar varios valores y cargar los mismos en los campos del formulario.
DEMO: https://fhumanes.com/scannerQR2/
Solución Técnica
El ejemplo intenta hacer la captura de Productos y en la opción de ADD, es donde se ha programado el ejemplo.
Como información de prueba en donde se recuperan datos están estos 2 códigos de producto. Puedes obtener un QR con el valor que quieras en esta URL: https://fhumanes.com/qr/
Para hacer la captura del valor del QR se ha programado un botón (de 3 estados) y desde él se crea una pantalla popup para hacer la captura. El código que se ha utilizado es:
var win = Runner.displayPopup( { url: "scannerqr_dummy_add.php", width: 900, height: 500, header: 'Read QR of the product', afterCreate: function(popup) { window.popup = popup; } }); return false;
Muy importante la sentencia «window.popup = popup;«, porque es la que nos va a dar la posibilidd de referenciar la ventana, en la nueva ventana.
En la página ADD, en el evento «JavaScript onload event» he puesto:
// --------------------------------------------------------------------------------- var ctrl_Product = Runner.getControl(pageid, 'productNumber'); window.ctrl_Product = ctrl_Product; // Export other pages // --------------------------------------------------------------------------------- var ctrl_amount = Runner.getControl(pageid, 'amount'); var ctrl_text = Runner.getControl(pageid, 'text'); // --------------------------------------------------------------------------------- ctrl_Product.on('blur', function (e) { // console.log('The "blur" event has jumped'); getValor(ctrl_Product,ctrl_amount, ctrl_text ); }); // ------------------------------------------------------------------------------------ function getValor(ctrl,f1,f2) { pvalor = ctrl.getValue(); $.ajax({ type: 'POST', url: './ajax_get_values.php', data: { valor: pvalor } }).done(function (msg) { // console.log("Into of the function"); // console.log(msg); response_as = JSON.parse(msg); // console.log(response_as.status); if (response_as.status == 'OK' ) { f1.setValue(response_as.amount); f2.setValue(response_as.text); } return ; }).fail(function (jqXHR, textStatus, errorThrown) { alert("The following error occured: " + textStatus + " " + errorThrown); }); }
En este código hay 2 partes:
- Para poder referenciar campos del formulario «padre».
Se utiliza la sentencia «window.ctrl_Product = ctrl_Product;« - Para recuperar los valores de los campos del servidor se utiliza;
- Evento «blur», perdida del foco del formulario para disparar la captura de información.
- Función «getValor» para que utilizando AJAX se recuperen los valores de los campos en formato JSON.
El código PHP para recuperar los datos del servidor es el programa «ajax_get_values.php» que tiene este código:
<?php require_once("include/dbcommon.php"); // DataBase PHPRunner $data_arr = array(); // Response if (!isset($_POST['valor'])) { // Control of the call and verification of the existence of the parameter $data_arr['status'] = 'KO'; $data_arr['msg'] = "Please provide a Valor."; echo json_encode($data_arr, JSON_UNESCAPED_UNICODE); die(); } $valor = $_POST['valor']; $data_arr['status'] = 'KO'; $rs = DB::Query("SELECT amount, text FROM scannerqr2_product WHERE productNumber = '$valor' "); while( $data = $rs->fetchAssoc() ) { $data_arr['status'] = 'OK'; $data_arr['amount'] = $data["amount"]; $data_arr['text'] = $data["text"]; } echo json_encode($data_arr, JSON_UNESCAPED_UNICODE); ?>
La explicación de la codificación puedes consultarla en este artículo.
En el evento «JavaScript Onload event» he codificado:
var ctrlQR = Runner.getControl(pageid, 'text'); ctrlQR.makeReadonly(); var ctrl_ext_QR = window.parent.ctrl_Product ; // Father Window Field var scanner = new Instascan.Scanner({ video: document.getElementById('preview'), scanPeriod: 5, mirror: false }); scanner.addListener('scan', function (content) { // alert(content); ctrlQR.setValue(content); // ctrl_ext_QR.setValue(content); // Campo de ventana padre var audio = new Audio('MyCode/beep.mp3'); audio.play(); }); Instascan.Camera.getCameras().then(function (cameras) { if (cameras.length > 0) { // alert('Camaras: '+ cameras.length); scanner.start(cameras[0]); $('[name="options"]').on('change', function () { if ($(this).val() == 1) { if (cameras[0] != "") { scanner.start(cameras[0]); } else { alert('No Front camera found!'); } } else if ($(this).val() == 2) { if (cameras[1] != "") { scanner.start(cameras[1]); } else { alert('No Back camera 1 found!'); } } else if ($(this).val() == 3) { if (cameras[2] != "") { scanner.start(cameras[2]); } else { alert('No Back camera 2 found!'); } } }); } else { console.error('No cameras found.'); alert('No cameras found.'); } }).catch(function (e) { console.error(e); alert(e); }); this.on('beforeSave', function(formObj, fieldControlsArr, pageObj){ var content = ctrlQR.getValue(); // Recover last value received window.parent.popup.close(); ctrl_ext_QR.setFocus(); ctrl_ext_QR.setValue(content); // Take the value to the father window field return true; });
Hay 3 partes en este código:
- La definición de los campos del formulario de su ventana y el campo de la ventana del formulario «padre». «var ctrl_ext_QR = window.parent.ctrl_Product ;«
- La parte específica de la cámara y lectura del QR.
- Y la parte de finalización del formulario con el evento «beforeSave» donde se captura el último valor del QR, se cierra la ventana popup, se establece el foco en el campo del formulario «padre» y se envía a dicho campo el nuevo valor.
Una vez que se cierra la ventana popup, el foco está en el campo (1) y cuando se sale de dicho campo la función AJAX recupera los valores y los pone en los campos (2).
Veréis que he utilizado en el campo «Product Number» el «lookup wizard»Si la entrada es manual, funciona perfectamente y recupera los valores de los campos, pero si el valor es recuperado desde la otra pantalla, no se dispara el evento de recuperación y es por lo que he tenido que programarlo.
Si alguien sabe o conoce cómo disparar dicho evento y me lo dice, podría modificar el ejemplo y divulgarlo al resto de desarrolladores.
Como siempre, os dejo el ejemplo completo para que lo podáis probar en vuestros equipos y cualquier duda, podéis comunicármela a través de mi email [email protected]