Related
I have a video application written in asp.net and c# with webRTC in JS.
some outsource wrote it for me a while ago (can't reach him any more) the application is working really good, except for one problem.
this video application was written for screen sharing use, and it uses some chrome extension for the screen sharing that also work good. the problem is that as soon as you go back from the screen sharing to the webcam stream, you cannot go back to the screen sharing stream. and it look like the programmer wrote this like this.
i tried turning on the extension again but it sends me an error. my question is, is there a way i can save the screen sharing stream and change the video feed with out touching the extension?
this is the js code for webrtc:
main problem in getfeed in the third 'if'
getFeed = function (shareScreen, username, userType, reinit, cb) {
if (shareScreen) {
$("#screen-share").attr("disabled", "disabled");
$("#video-share").removeAttr("disabled");
// getUserMedia(session, onSuccess, onError);
if (webrtcDetectedBrowser == "chrome") {
DetectRTC.screen.isChromeExtensionAvailable(function (isAvaliabe) {
if (isInScreenSharing) {
return;
}
if (isAvaliabe) {
isInScreenSharing = true;
captureUserMedia(onSuccess);
} else {
alertify.confirm("Screen sharing extension is not installed," +
" do you wish to install it now?",
function(e) {
if (e) {
window.open("https://chrome.google.com/webstore/detail/screen-capturing-
for-micr/hmppjaalobpkbpneompfdpfilcmfhfik", "_blank");
alertify.alert("Click Ok to reload page
after installing extension ", function () {
location.href = location.href;
});
}
});
}
});
} else {
isInScreenSharing = false;
getScreenId(function (error, sourceId, screen_constraints) {
screen_constraints.video = _showWebCam;
screen_constraints.audio = _showWebCam;
getUserMedia(screen_constraints, onSuccess, onError);
});
}
} else {
$("#video-share").attr("disabled", "disabled");
$("#screen-share").removeAttr("disabled");
getUserMedia(
{
// Permissions to request
video: _showWebCam,
audio: _showWebCam
}, onSuccess, onError);
}
function onSuccess(stream) { // succcess callback gives us a media stream
$('.instructions').hide();
if (reinit) {
if (screenStream) {
screenStream.getTracks().forEach(function (e) {
e.stop();
});
screenStream = null;
}
// Store off the stream reference so we can share it later
_mediaStream = stream;
if (webrtcDetectedBrowser == "chrome") {
if (shareScreen) {
//get the audio track from video stream and put it in screeen stream
var audioTrack = videoStream.getAudioTracks()[0];
var screenAudio = stream.getAudioTracks()[0];
if (screenAudio) {
_mediaStream.removeTrack(screenAudio)
}
_mediaStream.addTrack(audioTrack)
screenStream = _mediaStream;
} else {
videoStream = stream;
}
}
// Load the stream into a video element so it starts playing in the UI
console.log('playing my local video feed');
var videoElement = document.querySelector('.video.mine');
attachMediaStream(videoElement, _mediaStream);
if (cb) {
cb();
}
} else {
if (webrtcDetectedBrowser == "chrome") {
videoStream = stream;
}
var gameId =viewModel.GameId();
// Now we have everything we need for interaction, so fire up SignalR
_connect(username, userType,gameId, function (hub) {
// tell the viewmodel our conn id, so we can be treated like the special person we are.
viewModel.MyConnectionId(hub.connection.id);
// Initialize our client signal manager, giving it a
signaler (the SignalR hub) and some callbacks
console.log('initializing connection manager');
connectionManager.initialize(hub.server, _callbacks.onReadyForStream, _callbacks.onStreamAdded, _callbacks.onStreamRemoved);
// Store off the stream reference so we can share it later
_mediaStream = stream;
// Load the stream into a video element so it starts playing in the UI
console.log('playing my local video feed');
var videoElement = document.querySelector('.video.mine');
attachMediaStream(videoElement, _mediaStream);
// Hook up the UI
_attachUiHandlers();
viewModel.Loading(false);
if (cb) {
cb();
}
}, function (event) {
alertify.alert('<h4>Failed SignalR Connection</h4> We were not able to connect you to the signaling server.<br/><br/>Error: ' + JSON.stringify(event));
viewModel.Loading(false);
});
}
}
function onError(error) {
if (webrtcDetectedBrowser == "firefox") {
if (window.location.protocol === "https:") {
alertify.confirm("Screen sharing extension is not installed," +
" do you wish to install it now?",
function (e) {
if (e) {
InstallTrigger.install({ "ScreenShare": { URL: "https://addons.mozilla.org/firefox/downloads/file/457292/easy_screen_sharing_for_microgamecoaching_ltd-1.0.000-fx.xpi" } });
}
});
return;
}
}
alertify.alert(JSON.stringify(error));
viewModel.Loading(false);
}
},
_startSession = function (username, userType, gameId) {
// viewModel.Username(username); // Set the selected username in the UI
viewModel.Loading(true); // Turn on the loading indicator
// viewModel.UserType(userType); // Set the selected username in the UI
//viewModel.GameId(gameId);
if (location.hash === "#ss") {
getFeed(true, username, userType);
} else {
getFeed(false, username, userType);
}
$("#screen-share").click(function () {
getFeed(true, username, userType, true, function () {
var p = connectionManager.currentPartnerId;
connectionManager.closeAllConnections();
_hub.server.hangUp(true);
// _hub.server.callUser(p,true);
});
});
$("#video-share").click(function () {
getFeed(false, username, userType, true, function () {
var p = connectionManager.currentPartnerId;
connectionManager.closeAllConnections();
_hub.server.hangUp(true);
// _hub.server.callUser(p, true);
});
});
$("#mute").click(function () {
if (_mediaStream) {
_mediaStream.getAudioTracks().forEach(function (t) {
t.enabled = t.muted = false;
});
var videoElement = document.querySelector('.video.mine');
attachMediaStream(videoElement, _mediaStream);
}
});
$("#unmute").click(function () {
if (_mediaStream) {
_mediaStream.getAudioTracks().forEach(function (t) {
t.enabled = t.muted = true;
});
var videoElement = document.querySelector('.video.mine');
attachMediaStream(videoElement, _mediaStream);
}
});
},
_attachUiHandlers = function() {
// Add click handler to users in the "Users" pane
$(document).on("click", ".user", function () {
var userName = viewModel.Username();
if (!userName) {
alertify.alert("Please log in to enter the room", function() {
location.href = viewModel.LoginUrl() + "?returnUrl="+location.href;
});
return;
}
// Find the target user's SignalR client id
var targetConnectionId = $(this).attr('data-cid');
// Make sure we are in a state where we can make a call
if (viewModel.Mode() !== 'idle') {
alertify.error('Sorry, you are already in a call. Conferencing is not yet implemented.');
return;
}
// Then make sure we aren't calling ourselves.
if (targetConnectionId != viewModel.MyConnectionId()) {
// Initiate a call
_hub.server.callUser(targetConnectionId, false);
// UI in calling mode
viewModel.Mode('calling');
} else {
alertify.error("Ah, nope. Can't call yourself.");
}
});
$('#btnMessageSend').click(function() {
sendChatMessage();
});
$('#inpMessageText').keypress(function (e) {
if (e.keyCode === 13) {
sendChatMessage();
}
});
function sendChatMessage() {
var text = $('#inpMessageText').val();
if (text !== '') {
$('#inpMessageText').val('');
_hub.server.sendMessage(text, viewModel.MyConnectionId(), _callPartner.ConnectionId);
if (_lastMessageMine === null || !_lastMessageMine) {
$('#pnlMessagesContainer .message-container')
.append('<div><div class="autor">You</div><div class="message">' + text + '</div></div>');
} else {
$('#pnlMessagesContainer .message-container')
.append('<div><div class="message">' + text + '</div></div>');
}
_lastMessageMine = true;
}
$('#pnlMessagesContainer .message-container').scrollTop($('#pnlMessagesContainer .message-container').prop("scrollHeight"));
}
// Add handler for the hangup button
$('.hangup').click(function () {
// Only allow hangup if we are not idle
if (viewModel.Mode() != 'idle') {
_hub.server.hangUp(false);
connectionManager.closeAllConnections();
viewModel.Mode('idle');
$('#videoTitle').html('Coaching Session');
$('#videoPartnerName').html('');
$('#pnlMessagesContainer .message-container').empty();
$('#pnlChatContainer').hide();
}
});
$('input[name="rbtnWebcamToogle"]').change(function () {
_showWebCam = $(this).val() === "1";
if (!_showWebCam) {
//connectionManager.closeConnection(viewModel.MyConnectionId());
var mediaStream = _mediaStream.getVideoTracks()[0];
mediaStream.stop();
} else {
getFeed(false, viewModel.Username(), viewModel.UserType(), true, function () {
var p = connectionManager.currentPartnerId;
connectionManager.closeAllConnections();
_hub.server.hangUp(true);
});
}
});
},
_setupHubCallbacks = function (hub) {
// Hub Callback: Incoming Call
hub.client.incomingCall = function (callingUser, switching) {
console.log('incoming call from: ' + JSON.stringify(callingUser));
if (switching) {
hub.server.answerCall(true, callingUser.ConnectionId);
// So lets go into call mode on the UI
viewModel.Mode('incall');
$('#videoTitle').html('Your Session is LIVE');
$('#videoPartnerName').html('Your ' + callingUser.Usertype + ': ' + callingUser.Username);
return;
}
// Ask if we want to talk
alertify.confirm(callingUser.Username + ' is calling. Do you want to chat?', function (e) {
if (e) {
// I want to chat
hub.server.answerCall(true, callingUser.ConnectionId);
_callPartner = callingUser;
// So lets go into call mode on the UI
viewModel.Mode('incall');
$('#videoTitle').html('Your Session is LIVE');
$('#videoPartnerName').html('Your ' + callingUser.Usertype + ': ' + callingUser.Username);
$('#pnlMessagesContainer .message-container').empty();
$('#pnlChatContainer').show();
} else {
// Go away, I don't want to chat with you
hub.server.answerCall(false, callingUser.ConnectionId);
$('#videoTitle').html('Coaching Session');
$('#videoPartnerName').html('');
$('#pnlMessagesContainer .message-container').empty();
$('#pnlChatContainer').hide();
}
});
};
// Hub Callback: Call Accepted
hub.client.callAccepted = function (acceptingUser) {
console.log('call accepted from: ' + JSON.stringify(acceptingUser) + '. Initiating WebRTC call and offering my stream up...');
// Callee accepted our call, let's send them an offer with our video stream
connectionManager.initiateOffer(acceptingUser.ConnectionId, _mediaStream);
_callPartner = acceptingUser;
// Set UI into call mode
viewModel.Mode('incall');
$('#videoTitle').html('Your Session is LIVE');
$('#videoPartnerName').html('Your ' + acceptingUser.Usertype + ': ' + acceptingUser.Username);
$('#pnlMessagesContainer .message-container').empty();
$('#pnlChatContainer').show();
};
// Hub Callback: Call Declined
hub.client.callDeclined = function (decliningConnectionId, reason) {
console.log('call declined from: ' + decliningConnectionId);
_callPartner = null;
// Let the user know that the callee declined to talk
alertify.error(reason);
// Back to an idle UI
viewModel.Mode('idle');
};
// Hub Callback: Call Ended
hub.client.callEnded = function (connectionId, reason, switching) {
console.log('call with ' + connectionId + ' has ended: ' + reason);
if (!switching) {
// Let the user know why the server says the call is over
alertify.error(reason);
connectionManager.closeConnection(connectionId);
// Set the UI back into idle mode
viewModel.Mode('idle');
$('#pnlMessagesContainer .message-container').empty();
$('#pnlChatContainer').hide();
_callPartner = null;
$('#videoTitle').html('Coaching Session');
$('#videoPartnerName').html('');
} else {
connectionManager.closeConnection(connectionId);
_hub.server.callUser(connectionId, true);
}
// Close the WebRTC connection
};
hub.client.receiveMessage = function (senderUser, message) {
if (_lastMessageMine == null || _lastMessageMine) {
$('#pnlMessagesContainer .message-container')
.append('<div><div class="autor">' + senderUser.Username + '</div><div class="message">' + message + '</div></div>');
} else {
$('#pnlMessagesContainer .message-container')
.append('<div><div class="message">' + message + '</div></div>');
}
$('#pnlMessagesContainer .message-container').scrollTop($('#pnlMessagesContainer .message-container').prop("scrollHeight"));
_lastMessageMine = false;
}
// Hub Callback: Update User List
hub.client.updateUserList = function (userList) {
viewModel.setUsers(userList);
};
// Hub Callback: WebRTC Signal Received
hub.client.receiveSignal = function (callingUser, data) {
connectionManager.newSignal(callingUser.ConnectionId, data);
};
},
// Connection Manager Callbacks
_callbacks = {
onReadyForStream: function (connection) {
// The connection manager needs our stream
// todo: not sure I like this
connection.addStream(_mediaStream);
},
onStreamAdded: function (connection, event) {
console.log('binding remote stream to the partner window');
// Bind the remote stream to the partner window
var otherVideo = document.querySelector('.video.partner');
attachMediaStream(otherVideo, event.stream); // from adapter.js
},
onStreamRemoved: function (connection, streamId) {
console.log('removing remote stream from partner window');
// Clear out the partner window
var otherVideo = document.querySelector('.video.partner');
otherVideo.src = '';
}
};
return {
start: _start, // Starts the UI process
getStream: function() { // Temp hack for the connection manager to reach back in here for a stream
return _mediaStream;
}
};
})(WebRtcDemo.ViewModel, WebRtcDemo.ConnectionManager);
// Kick off the app
WebRtcDemo.App.start();
var isChrome = !!navigator.webkitGetUserMedia;
var DetectRTC = {};
(function () {
var screenCallback;
DetectRTC.screen = {
chromeMediaSource: 'screen',
getSourceId: function (callback) {
if (!callback) throw '"callback" parameter is mandatory.';
screenCallback = callback;
window.postMessage('get-sourceId', '*');
},
isChromeExtensionAvailable: function (callback) {
if (!callback) return;
if (DetectRTC.screen.chromeMediaSource == 'desktop') callback(true);
// ask extension if it is available
window.postMessage('are-you-there', '*');
setTimeout(function () {
if (DetectRTC.screen.chromeMediaSource == 'screen') {
callback(false);
} else callback(true);
}, 2000);
},
onMessageCallback: function (data) {
console.log('chrome message', data);
// "cancel" button is clicked
if (data == 'PermissionDeniedError') {
DetectRTC.screen.chromeMediaSource = 'PermissionDeniedError';
if (screenCallback) return
screenCallback('PermissionDeniedError');
else throw new Error('PermissionDeniedError');
}
// extension notified his presence
if (data == 'rtcmulticonnection-extension-loaded') {
DetectRTC.screen.chromeMediaSource = 'desktop';
}
// extension shared temp sourceId
if (data.sourceId) {
DetectRTC.screen.sourceId = data.sourceId;
if (screenCallback) screenCallback(DetectRTC.screen.sourceId);
}
}
};
// check if desktop-capture extension installed.
if (window.postMessage && isChrome) {
DetectRTC.screen.isChromeExtensionAvailable();
}
})();
window.addEventListener('message', function (event) {
if (event.origin != window.location.origin) {
return;
}
DetectRTC.screen.onMessageCallback(event.data);
});
function captureUserMedia(onStreamApproved) {
// this statement defines getUserMedia constraints
// that will be used to capture content of screen
var screen_constraints = {
mandatory: {
chromeMediaSource: DetectRTC.screen.chromeMediaSource,
maxWidth: 1920,
maxHeight: 1080,
minAspectRatio: 1.77
},
optional: []
};
// this statement verifies chrome extension availability
// if installed and available then it will invoke extension API
// otherwise it will fallback to command-line based screen capturing API
if (DetectRTC.screen.chromeMediaSource == 'desktop' && !DetectRTC.screen.sourceId) {
DetectRTC.screen.getSourceId(function (error) {
// if exception occurred or access denied
if (error && error == 'PermissionDeniedError') {
alert('PermissionDeniedError: User denied to share content of his screen.');
}
captureUserMedia(onStreamApproved);
});
return;
}
// this statement sets gets 'sourceId" and sets "chromeMediaSourceId"
if (DetectRTC.screen.chromeMediaSource == 'desktop') {
screen_constraints.mandatory.chromeMediaSourceId = DetectRTC.screen.sourceId;
}
// it is the session that we want to be captured
// audio must be false
var session = {
audio: false,
video: screen_constraints
};
// now invoking native getUserMedia API
navigator.webkitGetUserMedia(session, onStreamApproved, function (error){console.error(error)});
};
Hi I have the below page where you simply click the button Full screen and the page browser takes up the full screen, the navigation controls are also hidden to - which is what I like. However if you page refresh (or in my case my page refreshes every 5 minutes) the navigation controls return and it is no longer the view as previous. How can I solve this so that when it refreshed the navigation etc doesn't return and it remains full screen?
<html>
<head>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" />
<script src="screenfull.js"></script>
<script>
$(function () {
$('#supported').text('Supported/allowed: ' + !!screenfull.enabled);
if (!screenfull.enabled) {
return false;
}
$('#request').click(function () {
screenfull.request($('#container')[0]);
// does not require jQuery, can be used like this too:
// screenfull.request(document.getElementById('container'));
});
$('#exit').click(function () {
screenfull.exit();
});
function fullscreenchange() {
var elem = screenfull.element;
$('#status').text('Is fullscreen: ' + screenfull.isFullscreen);
if (elem) {
$('#element').text('Element: ' + elem.localName + (elem.id ? '#' + elem.id : ''));
}
if (!screenfull.isFullscreen) {
$('#external-iframe').remove();
document.body.style.overflow = 'hidden';
}
}
document.addEventListener(screenfull.raw.fullscreenchange, fullscreenchange);
// set the initial values
fullscreenchange();
});
</script>
<button id="request"><i class="fa fa-arrows-alt"></i> Request</button>
<button id="exit">Exit</button>
</body>
(function () {
'use strict';
var isCommonjs = typeof module !== 'undefined' && module.exports;
var keyboardAllowed = typeof Element !== 'undefined' && 'ALLOW_KEYBOARD_INPUT' in Element;
var fn = (function () {
var val;
var valLength;
var fnMap = [
[
'requestFullscreen',
'exitFullscreen',
'fullscreenElement',
'fullscreenEnabled',
'fullscreenchange',
'fullscreenerror'
],
// new WebKit
[
'webkitRequestFullscreen',
'webkitExitFullscreen',
'webkitFullscreenElement',
'webkitFullscreenEnabled',
'webkitfullscreenchange',
'webkitfullscreenerror'
],
// old WebKit (Safari 5.1)
[
'webkitRequestFullScreen',
'webkitCancelFullScreen',
'webkitCurrentFullScreenElement',
'webkitCancelFullScreen',
'webkitfullscreenchange',
'webkitfullscreenerror'
],
[
'mozRequestFullScreen',
'mozCancelFullScreen',
'mozFullScreenElement',
'mozFullScreenEnabled',
'mozfullscreenchange',
'mozfullscreenerror'
],
[
'msRequestFullscreen',
'msExitFullscreen',
'msFullscreenElement',
'msFullscreenEnabled',
'MSFullscreenChange',
'MSFullscreenError'
]
];
var i = 0;
var l = fnMap.length;
var ret = {};
for (; i < l; i++) {
val = fnMap[i];
if (val && val[1] in document) {
for (i = 0, valLength = val.length; i < valLength; i++) {
ret[fnMap[0][i]] = val[i];
}
return ret;
}
}
return false;
})();
var screenfull = {
request: function (elem) {
var request = fn.requestFullscreen;
elem = elem || document.documentElement;
// Work around Safari 5.1 bug: reports support for
// keyboard in fullscreen even though it doesn't.
// Browser sniffing, since the alternative with
// setTimeout is even worse.
if (/5\.1[\.\d]* Safari/.test(navigator.userAgent)) {
elem[request]();
} else {
elem[request](keyboardAllowed && Element.ALLOW_KEYBOARD_INPUT);
}
},
exit: function () {
document[fn.exitFullscreen]();
},
toggle: function (elem) {
if (this.isFullscreen) {
this.exit();
} else {
this.request(elem);
}
},
raw: fn
};
if (!fn) {
if (isCommonjs) {
module.exports = false;
} else {
window.screenfull = false;
}
return;
}
Object.defineProperties(screenfull, {
isFullscreen: {
get: function () {
return Boolean(document[fn.fullscreenElement]);
}
},
element: {
enumerable: true,
get: function () {
return document[fn.fullscreenElement];
}
},
enabled: {
enumerable: true,
get: function () {
// Coerce to boolean in case of old WebKit
return Boolean(document[fn.fullscreenEnabled]);
}
}
});
if (isCommonjs) {
module.exports = screenfull;
} else {
window.screenfull = screenfull;
}
})();
Online Demo : https://plnkr.co/edit/zx0rXwXpJbWdMvh3HQ25?p=preview
Make onepage website (ajax) (no refresh) Use history pushstate to save all your links so you can use history navigation and change your URL. (most of time I use this approach.)
Or you can use localstorage to save state.
Theoretically You can store an indication of what was the previews state (full-screen / normal) in the browser storage.
Then on page load, read the stored value and activate full-screen if necessary.
However, modern browsers require this to be an interactive user action (not automatically via script on load)
If you try to automate this, you'll get these type of warnings in the browser's console:
Alternatives
Avoid full refreshes
Workaround using custom browser extension to restore the fullscreen state
I have a problem with WinJS. I don't get the problem. I want to fill (and I do it) the autosuggestbox with data-items. After that, normally, it has to show the autosuggestbox. But WinJS does not draw the list.
HomeController:
(function () {
"use strict";
WinJS.UI.Pages.define("/pages/home/home.html", {
// This function is called whenever a user navigates to this page. It
// populates the page elements with the app’s data.
ready: function (element, options) {
var searchBox1 = document.querySelector("#station1");
var searchBox2 = document.querySelector("#station2");
searchBox1.addEventListener("suggestionsrequested", GuiEvents.stationRequest);
searchBox1.addEventListener("querysubmitted", Main.stationSubmittedHandler);
searchBox2.addEventListener("suggestionsrequested", GuiEvents.stationRequest);
searchBox2.addEventListener("querysubmitted", Main.stationSubmittedHandler);
WinJS.UI.processAll();
}
});
})();
The eventhandler:
static stationRequest(event: CustomEvent) {
var query = <string>event.detail.queryText;
var suggestionCollection = event.detail.searchSuggestionCollection;
var callback = function (response) {
event.detail.setPromise(WinJS.Promise.then(null, function () {
var _locations: Array<Object> = JSON.parse(response.responseText).LocationList.StopLocation;
$("#response").text(JSON.stringify(_locations));
_locations.forEach(function (obj: ILocation, index, _loc) {
suggestionCollection.appendQuerySuggestion(obj.name);
});
event.detail.linguisticDetails.queryTextAlternatives.forEach(
function (element, index, array) {
if (element.substr(0, query.length).toLocaleLowerCase() === query) {
suggestionCollection.appendQuerySuggestion(element);
}
});
}));
};
if (query.length > 3) {
API.stationRequest(query, callback);
}
}
I copied more or less the example form the windows WinJS site, but... It shows the responsetext very well to me in the $("#response")-element, but I get no box or list.
What is the failure.
I need to write a Firefox extension that creates a blacklist and whitelist of URL's, and checks to make sure the user wants to navigate to them whenever the user attempts to do so. I'm doing this using a main script and a content script that I attach to every page (using PageMod); I attached a listener using jQuery to every link (with the tag "a") which executes a function using window.onbeforeunload. I have two questions:
How would I prompt/ask the user if they actually did want to go to the site?
How would I stop the browser from navigating to the site if the user decided not to?
Right now my code passes messages between the two scripts in order to accomplish my goal; as far as I can tell, I can only use "document" in the content script, and save the blacklist/whitelist in the main script. I'm using simple-storage to save my lists, and the port module to pass messages between the scripts.
For question 1, I've attempted using confirm(message) to get a positive/negative response from the user, but the popup either doesn't show up or shows up for a split second then gets automatically answered with a negative response. When I look in my console's error messages, I see a "prompt aborted by user" error.
For question 2, I've already tried using event.preventDefault() by passing the click event to the function (this worked, I think). Is there a better way to do this? I've seen people using window.location = "", et cetera to do this.
Anyways, the code is below:
MAIN.JS
var ss = require("sdk/simple-storage");
exports.main = function() {
if (!ss.storage.blacklist) {
ss.storage.blacklist = [];}
if (!ss.storage.whitelist) {
ss.storage.whitelist = [];}
var data = require("sdk/self").data;
var pageMod = require("sdk/page-mod");
pageMod.PageMod({
include: "*",
contentScriptFile: [data.url("jquery-1.10.2.min.js"),data.url("secChk.js")],
onAttach: function(worker) {
function whiteCNTD(str) {
for (var index = 0; index < ss.storage.whitelist.length; index++) {
if (ss.storage.whitelist[index] == str) {
return index;
}
}
return -1;
}
function blackCNTD(str) {
for (var index = 0; index < ss.storage.blacklist.length; index++) {
if (ss.storage.blacklist[index] == str) {
return index;
}
}
return -1;
}
function checkLists(URL) {
if (whiteCNTD(URL) == -1) {
if (blackCNTD(URL) != -1) {
var bool = false;
worker.port.emit("navq", "Do you want to go to this link and add it to the whitelist?");
worker.port.on("yes", function() {
bool = true;
});
worker.port.on("no", function() {
bool = false;
});
if (bool == true) {
ss.storage.blacklist.splice(index, 1);
ss.storage.whitelist.push(URL);
return true;
}
else {
return false;
}
}
else {
var bool = false;
worker.port.emit("safeq", "Is this a safe site?");
worker.port.on("yes", function() {
bool = true;
});
worker.port.on("no", function() {
bool = false;
});
if (bool == true) {
ss.storage.whitelist.push(URL);
return true;
}
else {
ss.storage.blacklist.push(URL);
return false;
}
}
}
return true;
}
worker.port.on("newURL", function(URL) {
var s = "";
s = URL;
if (checkLists(s)) {
worker.port.emit("good", s);
} else if (!checkLists(s)) {
worker.port.emit("bad", s);
}
});
}
});
}
SECCHK.JS
//Check if the site is a bad site whenever a link is clicked
$("a").click(function(event) {
window.onbeforeunload = function() {
self.port.on("navq", function(message) {
var r = confirm("Do you want to go to this link and add it to the whitelist?");
if (r == true) {
self.port.emit("yes", message);
} else if (r == false) {
self.port.emit("no", message);
}
});
self.port.on("safeq", function(message) {
var r = confirm("Is this a safe site?");
if (r == true) {
self.port.emit("yes", temp);
} else if (r == false) {
self.port.emit("no", temp);
}
});
link = document.activeElement.href;
self.port.emit("newURL", link);
self.port.on("good", function(message) {
return true;
});
self.port.on("bad", function(message) {
return false;
});
}
});
How I can programmatically detect when text input filled by typing on keyboard and when it filled automatically by bar-code scanner?
I wrote this answer, because my Barcode Scanner Motorola LS1203 generated keypress event, so I can't use Utkanos's solution.
My solution is:
var BarcodeScanerEvents = function() {
this.initialize.apply(this, arguments);
};
BarcodeScanerEvents.prototype = {
initialize: function() {
$(document).on({
keyup: $.proxy(this._keyup, this)
});
},
_timeoutHandler: 0,
_inputString: '',
_keyup: function (e) {
if (this._timeoutHandler) {
clearTimeout(this._timeoutHandler);
this._inputString += String.fromCharCode(e.which);
}
this._timeoutHandler = setTimeout($.proxy(function () {
if (this._inputString.length <= 3) {
this._inputString = '';
return;
}
$(document).trigger('onbarcodescaned', this._inputString);
this._inputString = '';
}, this), 20);
}
};
Adapted the super useful Vitall answer above to utilize an IIFE instead of prototyping, in case anyone just seeing this now is into that.
This also uses the 'keypress' event instead of keyup, which allowed me to reliably use KeyboardEvent.key, since KeyboardEvent.which is deprecated now. I found this to work for barcode scanning as well as magnetic-strip card swipes.
In my experience, handling card swipes with keyup caused me to do extra work handling 'Shift' keycodes e.g. a Shift code would be followed by the code representing '/', with the intended character being '?'. Using 'keypress' solved this as well.
(function($) {
var _timeoutHandler = 0,
_inputString = '',
_onKeypress = function(e) {
if (_timeoutHandler) {
clearTimeout(_timeoutHandler);
}
_inputString += e.key;
_timeoutHandler = setTimeout(function () {
if (_inputString.length <= 3) {
_inputString = '';
return;
}
$(e.target).trigger('altdeviceinput', _inputString);
_inputString = '';
}, 20);
};
$(document).on({
keypress: _onKeypress
});
})($);
Well a barcode won't fire any key events so you could do something like:
$('#my_field').on({
keypress: function() { typed_into = true; },
change: function() {
if (typed_into) {
alert('type');
typed_into = false; //reset type listener
} else {
alert('not type');
}
}
});
Depending on when you want to evaluate this, you may want to do this check not on change but on submit, or whatever.
you can try following example, using jQuery plugin https://plugins.jquery.com/scannerdetection/
Its highly configurable, time based scanner detector. It can be used as solution for prefix/postfix based, time based barcode scanner.
Tutorial for usage and best practices, as well discussed about various Barcode Scanner Models and how to deal with it. http://a.kabachnik.info/jquery-scannerdetection-tutorial.html
$(window).ready(function(){
//$("#bCode").scannerDetection();
console.log('all is well');
$(window).scannerDetection();
$(window).bind('scannerDetectionComplete',function(e,data){
console.log('complete '+data.string);
$("#bCode").val(data.string);
})
.bind('scannerDetectionError',function(e,data){
console.log('detection error '+data.string);
})
.bind('scannerDetectionReceive',function(e,data){
console.log('Recieve');
console.log(data.evt.which);
})
//$(window).scannerDetection('success');
<input id='bCode'type='text' value='barcode appears here'/>
For ES6 2019 version of Vitall answer.
const events = mitt()
class BarcodeScaner {
initialize = () => {
document.addEventListener('keypress', this.keyup)
if (this.timeoutHandler) {
clearTimeout(this.timeoutHandler)
}
this.timeoutHandler = setTimeout(() => {
this.inputString = ''
}, 10)
}
close = () => {
document.removeEventListener('keypress', this.keyup)
}
timeoutHandler = 0
inputString = ''
keyup = (e) => {
if (this.timeoutHandler) {
clearTimeout(this.timeoutHandler)
this.inputString += String.fromCharCode(e.keyCode)
}
this.timeoutHandler = setTimeout(() => {
if (this.inputString.length <= 3) {
this.inputString = ''
return
}
events.emit('onbarcodescaned', this.inputString)
this.inputString = ''
}, 10)
}
}
Can be used with react hooks like so:
const ScanComponent = (props) => {
const [scanned, setScanned] = useState('')
useEffect(() => {
const barcode = new BarcodeScaner()
barcode.initialize()
return () => {
barcode.close()
}
}, [])
useEffect(() => {
const scanHandler = code => {
console.log(code)
setScanned(code)
}
events.on('onbarcodescaned', scanHandler)
return () => {
events.off('onbarcodescaned', scanHandler)
}
}, [/* here put dependencies for your scanHandler ;) */])
return <div>{scanned}</div>
}
I use mitt from npm for events, but you can use whatever you prefer ;)
Tested on Zebra DS4208
The solution from Vitall only works fine if you already hit at least one key. If you don't the first character will be ignored (if(this._timeoutHandler) returns false and the char will not be appended).
If you want to begin scanning immediately you can use the following code:
var BarcodeScanerEvents = function() {
this.initialize.apply(this, arguments);
};
BarcodeScanerEvents.prototype = {
initialize : function() {
$(document).on({
keyup : $.proxy(this._keyup, this)
});
},
_timeoutHandler : 0,
_inputString : '',
_keyup : function(e) {
if (this._timeoutHandler) {
clearTimeout(this._timeoutHandler);
}
this._inputString += String.fromCharCode(e.which);
this._timeoutHandler = setTimeout($.proxy(function() {
if (this._inputString.length <= 3) {
this._inputString = '';
return;
}
$(document).trigger('onbarcodescaned', this._inputString);
this._inputString = '';
}, this), 20);
}
};
If you can set a prefix to your barcode scanner I suggests this (I changed a bit the Vitall code):
var BarcodeScanner = function(options) {
this.initialize.call(this, options);
};
BarcodeScanner.prototype = {
initialize: function(options) {
$.extend(this._options,options);
if(this._options.debug) console.log("BarcodeScanner: Initializing");
$(this._options.eventObj).on({
keydown: $.proxy(this._keydown, this),
});
},
destroy: function() {
$(this._options.eventObj).off("keyup",null,this._keyup);
$(this._options.eventObj).off("keydown",null,this._keydown);
},
fire: function(str){
if(this._options.debug) console.log("BarcodeScanner: Firing barcode event with string: "+str);
$(this._options.fireObj).trigger('barcode',[str]);
},
isReading: function(){
return this._isReading;
},
checkEvent: function(e){
return this._isReading || (this._options.isShiftPrefix?e.shiftKey:!e.shiftKey) && e.which==this._options.prefixCode;
},
_options: {timeout: 600, prefixCode: 36, suffixCode: 13, minCode: 32, maxCode: 126, isShiftPrefix: false, debug: false, eventObj: document, fireObj: document},
_isReading: false,
_timeoutHandler: false,
_inputString: '',
_keydown: function (e) {
if(this._input.call(this,e))
return false;
},
_input: function (e) {
if(this._isReading){
if(e.which==this._options.suffixCode){
//read end
if(this._options.debug) console.log("BarcodeScanner: Read END");
if (this._timeoutHandler)
clearTimeout(this._timeoutHandler);
this._isReading=false;
this.fire.call(this,this._inputString);
this._inputString='';
}else{
//char reading
if(this._options.debug) console.log("BarcodeScanner: Char reading "+(e.which));
if(e.which>=this._options.minCode && e.which<=this._options.maxCode)
this._inputString += String.fromCharCode(e.which);
}
return true;
}else{
if((this._options.isShiftPrefix?e.shiftKey:!e.shiftKey) && e.which==this._options.prefixCode){
//start reading
if(this._options.debug) console.log("BarcodeScanner: Start reading");
this._isReading=true;
this._timeoutHandler = setTimeout($.proxy(function () {
//read timeout
if(this._options.debug) console.log("BarcodeScanner: Read timeout");
this._inputString='';
this._isReading=false;
this._timeoutHandler=false;
}, this), this._options.timeout);
return true;
}
}
return false;
}
};
If you need you customize timeout, suffix, prefix, min/max ascii code readed:
new BarcodeScanner({timeout: 600, prefixKeyCode: 36, suffixKeyCode: 13, minKeyCode: 32, maxKeyCode: 126});
I also added the isShiftPrefix option to use for example the $ char as prefix with these options: new BarcodeScanner({prefixKeyCode: 52, isShiftPrefix: true});
This is a fiddle: https://jsfiddle.net/xmt76ca5/
You can use a "onkeyup" event on that input box. If the event has triggered then you can called it "Input from Keyboard".
$(window).ready(function(){
//$("#bCode").scannerDetection();
console.log('all is well');
$(window).scannerDetection();
$(window).bind('scannerDetectionComplete',function(e,data){
console.log('complete '+data.string);
$("#bCode").val(data.string);
})
.bind('scannerDetectionError',function(e,data){
console.log('detection error '+data.string);
})
.bind('scannerDetectionReceive',function(e,data){
console.log('Recieve');
console.log(data.evt.which);
})
//$(window).scannerDetection('success');
<input id='bCode'type='text' value='barcode appears here'/>
Hi I have and alternative solution for evaluate a result of the bar code scanner without use of jQuery, first you need and input text that have a focus the moment that the barcode scanner is works
<input id="input_resultado" type="text" />
The code in JavaScript is:
var elmInputScan = document.getElementById('input_resultado');
elmInputScan.addEventListener('keypress', function (e){
clearInterval( timer_response );
timer_response = setTimeout( "onInputChange()", 10);
});
When the barcode scanner input the text call serveral times to the keypress event, but only I interested to the final result, for this reason I use the timer. That's all, you can process the value into the onInputChange function.
function onInputChange() {
console.log( document.getElementById('input_resultado').value );
}
document.addEventListener("keypress", function (e) {
if (e.target.tagName !== "INPUT") {
// it's your scanner
}
});
None of the solutions worked for me because I don't want to focus on an input. I want the result page(item details page) to keep listening for the scanner to scan next item. My scanner fires the keypress event so this worked like a charm for me.
var inputTemp = '';
var inputTempInterval = setInterval(function() {
// change 5 as minimum length of the scan code
if (inputTemp.length >= 5) {
var detected = inputTemp;
inputTemp = '';
clearInterval(inputTempInterval); // stop listening if you don't need anymore
onScannerTrigger(detected);
} else {
inputTemp = '';
}
}, 100);
$(window).keypress(function(e){
inputTemp += String.fromCharCode(e.which);
});
function onScannerTrigger(scannedCode) {
console.log(scannedCode);
// do your stuff
}
I have published a lightweight JS package which doesn't rely on jQuery or input fields. It simple looks at the timing of the keyPress-events to determine wether it was a barcode scanner or regular input.
https://www.npmjs.com/package/#itexperts/barcode-scanner
import {BarcodeScanner} from "#itexperts/barcode-scanner";
let options = {
timeOut: 130,
characterCount: 13
}
let barcodeScanner = new BarcodeScanner(options);
barcodeScanner.addEventListener('scan', function(e){
let barcode = e.detail;
console.log(barcode);
});
I highly recommend this js plugin https://github.com/axenox/onscan.js
It's easy to use and has tones of options to meet your need.
<script src="path-to-onScan.js"></script>
<script>
// Initialize with options
onScan.attachTo(document, {
suffixKeyCodes: [13], // enter-key expected at the end of a scan
reactToPaste: true, // Compatibility to built-in scanners in paste-mode (as opposed to keyboard-mode)
onScan: function(sCode, iQty) { // Alternative to document.addEventListener('scan')
console.log('Scanned: ' + iQty + 'x ' + sCode);
},
onKeyDetect: function(iKeyCode){ // output all potentially relevant key events - great for debugging!
console.log('Pressed: ' + iKeyCode);
}
});
</script>