Skip to content

Instantly share code, notes, and snippets.

@lyellick
Last active September 5, 2023 23:45
Show Gist options
  • Save lyellick/68787d37b10bb7f17e11deddcfe9f974 to your computer and use it in GitHub Desktop.
Save lyellick/68787d37b10bb7f17e11deddcfe9f974 to your computer and use it in GitHub Desktop.
WebNFC JavaScript Class Wrapper
class WebNFC {
constructor(scan) {
this.scan = scan;
}
async read(read) {
if ('NDEFReader' in window) {
const reader = new NDEFReader();
const abortController = new AbortController();
const permissionStatus = await navigator.permissions.query({ name: "nfc" });
// Abort NFC Scanning Trigger
abortController.signal.onabort = signal => {
if ('stopped' in this.scan) {
// On NFC Scanning Stopped
this.scan.stopped(signal);
}
};
await reader.scan({ signal: abortController.signal }).then(() => {
reader.onerror = () => {
if ('error' in read) {
// On NFC Read Error
read.error();
}
};
reader.onreading = tag => {
if ('success' in read) {
// On NFC Read Success
read.success(tag);
}
};
}).catch(error => {
if ('error' in this.scan) {
// On NFC Scan Error
this.scan.error(error);
}
});
if (permissionStatus.state !== 'granted') {
if ('denied' in this.scan) {
// NFC Perrmission Denied By User
this.scan.denied();
}
} else {
if ('granted' in this.scan) {
// NFC Perrmission Granted By User
this.scan.granted();
}
}
if ('stop' in this.scan) {
// Stop NFC Scanning
this.scan.stop(abortController);
}
} else {
if ('unsupported' in this.scan) {
// NFC Read Not Support in Browser (Only Chrome 81 to <= 83 Supported)
this.scan.unsupported();
}
}
}
async write(action) {
if ('NDEFWriter' in window) {
// Write Tag
} else {
// NFC Write Not Support in Browser (Only Chrome 81 to <= 83 Supported)
}
}
}
try {
Object.defineProperty(NDEFRecord.prototype, 'textRecordToString', {
value: function textRecordToString() {
if (this.recordType === 'text') {
const decoder = new TextDecoder(this.encoding);
return decoder.decode(this.data);
}
},
writable: true,
configurable: true
});
} catch {
console.warn("Web NFC is not supported for this device");
}
var scan = {
error: function (error) {
// NFC Scan Error Event
},
stop: function (abortController) {
// NFC Stop Scan Event
// Stop NFC scanning by executing abortController.abort()
document.getElementById("nfc-switch").addEventListener("change", function () {
if (!this.checked) {
abortController.abort();
console.log("NFC Read Disabled");
}
});
},
stopped: function (signal) {
// NFC Scanning Stopped Event
},
denied: function () {
// NFC Is Denied Event
// Remediation: Go to Browser Settings > Advanced > Site Settings > NFC Devices > Select "${location.host}" > Select NFC Devices > Allow
},
granted: function () {
// NFC Is Granted Event
},
unsupported: function () {
// NFC Not Supported In Browser Event
}
}
var read = {
success: function (tag) {
var serialNumber = tag.serialNumber;
var message = tag.message;
for (const record of message.records) {
switch (record.recordType) {
case "empty":
break;
case "text":
var recordText = record.textRecordToString();
console.log(recordText);
break;
case "url":
break;
case "smart-poster":
break;
case "absolute-url":
break;
case "mime":
break;
case "unknown":
default:
break;
}
}
},
error: function () {
console.log('read failed');
}
}
document.getElementById("nfc-switch").addEventListener("change", function () {
if (this.checked) {
new WebNFC(scan).read(read);
console.log("NFC Read Enabled");
}
});
@lyellick
Copy link
Author

lyellick commented Apr 9, 2021

If you happen to test this while having YouTube/App hovering over a webpage the NFC permission will not allow. Close any app controls that hover over the webpage will allow you to enable the NFC permission.

Issue: w3c/web-nfc#616
Bug Request: https://bugs.chromium.org/p/chromium/issues/detail?id=1198082

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment