Hello Vinh,
I have found a sample on a Japanese page.
This sample does not create the native app and reads the QR code on the web browser.
Note that this customization only works on iOS Safari.
You would need Node.js 10 environment.
Here is an idea of what the customization looks like;
・You click the [Scan] button at the top of the Add Record screen to display a modal to read the QR code.
・Then you scan the QR code and click the [OK] button to get the product name from the product master in the lookup.
・You can enter the incoming and outgoing information and save the record.
Create the following apps;
“Receiving and Shipping History App”
This is an app to customize barcode reading. Customize this app with JavaScript.
Field Name / Field Type / Field Code / Notes
Product Code / Look Up / itemCode / Associate with a product code in the product master
Product Name / Text(1 row) / itemName / Copies from the product name in the product master
Type / Radio Button / - / Receiving and Shipping
Quantity / Numeric Value / - / Initial value: 0
“Product Master”
This is an app to be associated with the Receive/Shipping history. This one is not customized.
Add the product records to this application beforehand.
Field Name / Field Type / Field Code / Notes
Code / Text(1 row) / itemCode / Check " Prohibit duplicated values".
Product Name / Text (1 row) / itemName
You will use InstaScan as the library to read 2D barcodes.
However, it doesn’t work in mobile Safari, so there is InstaScan1, which is forked.
https://github.com/chick-p/instascan
-
Access the forked InstaScan and download the repository.
-
Execute the following command under the repository directory, using Node.js 10.
Go to the repository directory
$ cd instascan-master
Install the tools required for the build
$ npm install
Build
$ npx gulp release
-
Under the dist directory, “instascan.min.js” will be generated. It will be used in “Applying kintone customization” later on.
Apply customization to the “Receiving/Shipping History” app.
JavaScript files for smartphones (applied in the following order):
- https://js.cybozu.com/jquery/3.4.1/jquery.min.js
- instascan.min.js
- customize.js (customization file)
CSS file for smartphones:
-
customize.css (customize file)
The details of the customize file (customize.js customize.css ) are as follows.
Since it runs in Safari, it uses ES6+ notation.
(($) => {
‘use strict’;
let camera, result;
/**
- Generate the HTML for the scan button
-
@return {Object} scanButtonHTML
*/
const getScanBtnHTML = () => {
return `
scan
`;
};
/**
- Generate modal HTML
-
@return {Object} modalHTML
*/
const getModalHTML = () => {
return `
`;
};
/**
- Create a scanner object
-
@param {jQuery} $modal
-
@return {Object} Scanner
*/
const getScanner = ($modal) => {
const $video = $modal.find(’#video’);
const scanner = new Instascan.Scanner({video: $video[0], mirror: false});
// Register an event when a read is taken
scanner.addListener(‘scan’, (_result) => {
result = _result;
$(’.js-kpc-modal__footer button[name=“ok”]’).prop(‘disabled’, false);
$(‘input[name=“itemCode”]’).val(result);
});
return scanner;
};
/**
- Open modal
*/
const openModal = () => {
if ($(’.kcp-modal’).length > 0) {
$(’.kcp-modal’).remove();
}
const $modal = $(getModalHTML());
$(‘body’).append($modal);
$(‘input[name=“itemCode”]’).val(’’);
const scanner = getScanner($modal);
Instascan.Camera.getCameras().then((cameras) => {
if (cameras.length <= 0) {
console.error(‘No cameras found.’);
return;
}
camera = cameras[0];
scanner.start(camera);
}).catch((err) => {
console.error(err);
});
$(’.js-kpc-modal__footer button[name=“ok”]’).on(‘click’, () => {
const record = kintone.mobile.app.record.get();
record.record.itemCode.value = result;
record.record.itemCode.lookup = true;
kintone.mobile.app.record.set(record);
closeModal(scanner);
});
$(’.js-kpc-modal__footer button[name=“cancel”]’).on(‘click’, () => {
closeModal(scanner);
});
$(’.js-kpc-modal bg,.js-kcp-modal cointainer’).fadeIn(‘slow’);
};
/**
- Close modal
-
@param {Object} scanner scanner
*/
const closeModal = (scanner) => {
$(’.js-kcp-modal cointainer,.js-kpc-modal bg’).fadeOut(‘slow’, () => {
$(’.js-kpc-modal__bg’).remove();
if (camera) {
scanner.stop(camera);
}
});
};
// Run when the Add Record screen of the mobile version is opened.
kintone.events.on(‘mobile.app.record.create.show’, (event) => {
const $scanBtn = $(getScanBtnHTML());
$(kintone.mobile.app.getHeaderSpaceElement()).append($scanBtn);
$scanBtn.find(’.js-kcp-button’).on(‘click’, () => {
openModal();
});
return event;
});
})(jQuery);
*******************
.kpc-header {
padding: 10px;
}
.kpc-btn {
padding: 8px 12px;
font-size: 1em;
font-weight: 700;
line-height: 1;
color: #fff;
background-color: #206694;
border: solid 2px #206694;
border-radius: 6px;
}
.kpc-modal__bg {
position: fixed;
top: 0;
left: 0;
z-index: 1;
display: none;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
}
.kcp-modal__cointainer {
position: fixed;
top: 2vh;
right: 5vh;
left: 5vh;
z-index: 2;
max-height: 95vh;
background-color: #fff;
border-radius: 6px 6px 6px 6px;
}
.kpc-modal__header {
padding: 16px;
font-size: 1.4rem;
font-weight: 700;
line-height: 1.4em;
border-bottom: 1px solid #d8d8d8;
}
.kpc-video__container {
position: relative;
padding: 16px;
line-height: 1.4em;
border-bottom: 1px solid #d8d8d8;
}
.video {
top: 0;
z-index: 1;
width: 100%;
}
.kcp-modal__result {
position: relative;
-webkit-box-sizing: border-box;
box-sizing: border-box;
width: 100%;
padding: 16px;
}
.kcp-modal__result dl {
width: 100%;
}
.kcp-modal__result dt {
margin-bottom: 5px;
font-weight: 700;
}
.kcp-modal__result dd {
width: 100%;
margin-bottom: 5px;
}
.kpc-modal__footer {
display: flex;
padding: 10px 16px;
}
.kpc-modal__footer--left {
display: flex;
float: left;
width: 50%;
}
.kpc-modal__footer--right {
display: flex;
float: right;
width: 50%;
text-align: right;
}
.kpc-modal__footer button {
box-sizing: border-box;
display: block;
min-width: 100px;
padding: 12px;
font-weight: 700;
line-height: 1;
border: 2px solid #206694;
border-radius: 6px;
}
.kpc-modal__footer button[name="ok"] {
margin: 0 0 0 auto;
color: #fff;
background-color: #206694;
}
.kpc-modal__footer button[disabled] {
cursor: default;
background-color: #a5a5a5;
border: 2px solid #a5a5a5;
}
.kpc-modal__footer button[name="cancel"] {
color: #206694;
background-color: #fff;
}
.kcp-modal__result input {
-webkit-box-sizing: border-box;
box-sizing: border-box;
width: 100%;
padding: 0.4em;
border-radius: 0.4em;
outline: 0;
}
.kcp-modal__result input[disabled] {
-webkit-box-sizing: border-box;
box-sizing: border-box;
color: #999;
-webkit-text-fill-color: #999;
background-color: #d5d7d9;
opacity: 1;
}
.qrcode {
padding-right: 1.7em;
margin-right: 0;
vertical-align: middle;
}
This way, you can read QR codes with a small amount of JavaScipt customization without creating a native app!
Hopefully, it helps.