javascript issue with Mozilla firefox when zoom is above 130% - javascript

We use a 3rd part framework called AribaWeb where the UI HTML is rendered by backend server, but javascript is used to handle all the UI events on the client side.
Since I am unfamiliar with javascript, i am seeking help here.
The issue we are seeing happens only with following conditions:
Mozilla Firefox is the browser. Latest version included. Not reproducible in any other browsers.
Zoom level set is above 130%
Fairly long form hence there is vertical scrolling
Steps and issue:
when users go to the end of the form and select a button or select a radio button, the page "jumps", in other words the focus shifts to the top of the page.
This happens very inconsistently.
I found the following old stackoverflow article and tried the solution, but no luck. jQuery Focus fails on firefox
Any hints/clues will be helpful.
I have been debugging the following function to find out clues, but unfortunately the scroll to the top of the page happens much before this function is invoked:
/////////////////////////////////////////
// Precendence: //
// first text in focus region //
// current browser active element //
// first text on page if allowed //
/////////////////////////////////////////
focusOnActiveElement : function () {
if (AWFocusRegionId) {
var focusRegion = Dom.getElementById(AWFocusRegionId);
AWFocusRegionId = null;
if (focusRegion) {
var firstRegionText = this.findFirstText(focusRegion);
if (firstRegionText) {
AWActiveElementId = firstRegionText.id;
}
}
}
if (AWActiveElementId) {
try {
var activeElement = Dom.getElementById(AWActiveElementId);
if (Dom.elementInDom(activeElement) &&
!this.modallyDisabled(activeElement)) {
Debug.log("Focusing on element id: " + AWActiveElementId);
var activeElementId = AWActiveElementId;
function checkFocus () {
try {
// no active element, refocus
if (!Dom.getActiveElementId()) {
Debug.log("Refocusing on element id: " + activeElementId);
if (activeElement.focus) {
activeElement.focus();
activeElement.focus();
if (activeElement.select) {
activeElement.select();
}
}
}
}
catch (fe) {
Debug.log("Exceotion ",fe);
}
}
function fcs() {
if (activeElement.focus) {
activeElement.focus();
activeElement.focus();
if (activeElement.select) {
activeElement.select();
}
}
}
setTimeout(checkFocus, 1000);
setTimeout(fcs,0);
}
}
catch (e) {
Debug.log("Focusing exception: " + e);
}
finally {
AWActiveElementId = null;
}
}
if (!Dom.getActiveElementId() && AWAllowSelectFirstText) {
AWAllowSelectFirstText = false;
Debug.log("Focusing on first text: ");
this.selectFirstText();
}
}

Related

Old JavaScript no longer working. Chrome says Event.path is deprecated, but I don't use Event.path in my code

I built a game of concentration over a year ago. I tried to run it today and when you click on the back of a "card" it's supposed to reveal a picture, but it does not. Chrome dev tools says "Event.path is deprecated and will be removed. Please use Event.composedPath() instead."
Nowhere in my code do I use Event.path and I can't seem to figure out what specifically is broken.
Here is the code I do have for a click event. The first function is repeated for all 24 cards and calls the second function which is supposed to reveal the picture "underneath" the back of the card and if both revealed pictures are the same they remain revealed, otherwise they both get reset to show the back of the card.
//onClick functions for all card images
pic1.onclick = () => {
console.log(revealedPics); //this sends the file link of the revealed picture to the console
if (isClicked(pic1) === false) {
pic1.src = picArray[0];
checkIfMatch(pic1);
} else if (trackRevealedCardsArray.includes(pic1.src) === true) {
return;
} else {
pic1.src = backOfCard;
}
console.log(revealedPics);
}
//Check if two revealed images are a match
const checkIfMatch = (pic) => {
if (revealedPics === 1) {
firstPic = pic;
} else if (revealedPics === 2) {
secondPic = pic;
if (firstPic.src === secondPic.src) {
revealedPics = 0;
totalPairs--;
trackRevealedCardsArray.push(firstPic.src);
console.log(`total pairs ${totalPairs}`);
if (totalPairs === 0) {
window.setTimeout(gameOver, 500);
}
} else {
window.setTimeout(function() {
firstPic.src = backOfCard;
secondPic.src = backOfCard;
}, 800);
window.setTimeout(resetRevealedPics, 800);
}
}
}
I've checked to make sure all my paths are correct and they are. When I run the same html files from my local drive it works perfectly.

chrome.tabs.update stops working when called from extension

I tried the following code. It basically takes a screenshot from all tabs open in the current window:
function captureWindowTabs(windowId, callbackWithDataUrlArray) {
var dataUrlArray = [];
// get all tabs in the window
chrome.windows.get(windowId, { populate: true }, function(windowObj) {
var tabArray = windowObj.tabs;
// find the tab selected at first
for(var i = 0; i < tabArray.length; ++i) {
if(tabArray[i].active) {
var currentTab = tabArray[i];
break;
}
}
// recursive function that captures the tab and switches to the next
var photoTab = function(i) {
chrome.tabs.update(tabArray[i].id, { active: true }, function() {
chrome.tabs.captureVisibleTab(windowId, { format: "png" }, function(dataUrl) {
// add data URL to array
dataUrlArray.push({ tabId:tabArray[i].id, dataUrl: dataUrl });
// switch to the next tab if there is one
if(tabArray[i+1]) {
photoTab(i+1);
}
else {
// if no more tabs, return to the original tab and fire callback
chrome.tabs.update(currentTab.id, { active: true }, function() {
callbackWithDataUrlArray(dataUrlArray);
});
}
});
});
};
photoTab(0);
});
}
When I call this code from popup.html opened as a webpage, it works as expected (I trigger this from a button click in the popup.html). When I call it from the browser extension, it just gets interrupted from the first tab it selects. Any idea why that is? I can't share errors, since the debugger gets closed when called from the extension.
Supplementary, is there a way to achieve desired result without needing the visual tab switching?
While updating the next tab as active tab. make sure current tab is no more active tab by doing
chrome.tabs.update(tabArray[i-1].id, { active: false }, ()=>{});
Moving the extension to a background script fixed the problem.
Reasoning is that the popup will close once the tab switches. Hence it is required to run in the background where it is not interrupted when the popup closes.

Checking if a page is up prior to loading the page

We need a solution to the following issue.
We currently refresh a screen every 30 seconds, what we need to do prior to the actual refresh is check if the website is still up and if there is a network present to access the page.
If the page is down then we delay the refresh by 6 seconds this is repeated 5 times.
If the fifth attempt is showing that the website is still down then an error message is displayed.
This is working fine but we need to check if the website is still available (ping the website prior to refreshing) and also we need a solution if the browser starts to refresh but loses the connection or the server goes down once the refresh has started
This is the current code
window.onload = function () {
var refresh_rate = 30; //<-- Second until refresh
var connection_attempts=5; ////// Connection attempts
var failed_seconds=6;
var inactivity_counter = 0;
var connection_failed= 0;
function reset1() {
inactivity_counter = 0;
console.log("Reset1");
}
function reset2() {
inactivity_counter = 0;
console.log("Reset2");
}
function reset3() {
inactivity_counter = 0;
connection_failed = 0;
console.log("Reset3");
}
function reset_network() {
inactivity_counter = (refresh_rate - failed_seconds);
console.log("ResetNetwork");
}
setInterval(function () {
inactivity_counter++;
refreshCheck();
}, 1000);
function can_i_refresh() {
if (inactivity_counter >= refresh_rate) {
return true;
}
return false;
}
function refreshCheck() {
if (can_i_refresh()) {
if(navigator.onLine) {
connection_failed='0';
window.location.href='alreadybooked.php?location=5';
inactivity_counter = 0;
}
else {
connection_failed++;
console.log(connection_failed);
if(connection_failed==connection_attempts) {
alert("Error 1001: This check-in device is currently experiencing issues. Please check-in on another device. If you still experience issues, please press the 'OK' button and proceed to reception");
return false;
}
reset_network();
}
}
else {
console.log(inactivity_counter);
}
}
window.addEventListener("click", reset1);
window.addEventListener("mousemove", reset2);
};
This should do what you need.
The function setupPageReload() creates a timeout so that the page reload will start after the specified delay. The actual reload is done into a temporary element, so the check for availability and the reload are the same thing. If the reload doesn't happen (for any reason) then the fail counter is incremented and will execute the fatalError() function if there have been enough retries. If it works then it simply replaces the contents of the current page with the contents that were just downloaded. Unless there was a "fatal error" then the function is simply executed again to start the process all over.
var refreshRate = 30;
var connectionAttempts = 5;
var connectionFailed = 0;
function setupPageReload() {
setTimeout(function() {
$("<div/>").load(location.href + " body", function(response, status) {
if (status == "success") {
connectionFailed = 0;
$("body").html(response);
setupPageReload();
}
else {
if (++connectionFailed === connectionAttempts) {
fatalError();
}
else {
setupPageReload();
}
}
});
}, refreshRate * 1000);
}
function fatalError() {
alert("Error 1001: This check-in device is currently experiencing issues. " +
"Please check-in on another device. If you still experience issues, " +
"please press the 'OK' button and proceed to reception");
}
window.onload = setupPageReload;
Incidentally, this method requires jQuery as that performs the ajax download and gets the content of the <body/> tag much, much easier than if you were to do that in vanilla js. If you don't already use that in the page in question then you'll need to add a script include.

JavaScript bind element events as soon as element is loaded

I want to make things happen with DOM elements as soon as they are loaded (found nothing with search on this site or Google, but it is hard to explain this with few words). For example, when a big page is loading I want to hide/add onlick events/etc. to elements as soon as they appear on user's screen not on $(document).ready(). I wrote a simple class (just for training, closures are new for me so there may be lots of errors) that does what I want but I want to use something better for commercial useb(on the site I'm helping to develop). Here is my source code:
function MY_loader() {
function container() {
this.add_event = function(new_event,obj_selector,settings) {
if(typeof(settings)!='object') {
settings={};
}
if(typeof(settings.event_id)!='string') {
settings.event_id=gen_new_event_id();
}
settings=$.extend({},default_settings,settings);
settings.obj_selector=obj_selector;
settings.event=new_event;
events[settings.event_id]=settings;
}
this.execute_events = function(if_force) {
if(typeof(if_force)=='undefined') {
if_force=false;
}
if(html_is_loaded&&!if_force) {
return;
}
var temp_obj;
for(var event_name in events) {
temp_obj=$(events[event_name].obj_selector);
if(temp_obj.length || (html_is_loaded && events[event_name].if_force)) {
temp_obj.each(function() {
if(events[event_name].expect_multiple) {
if($(this).data('my_loader_'+events[event_name].event_id+'_executed')) {
return;
}
}
if(events[event_name].event_type!='func') {
$(this).bind(events[event_name].event_type+'.'+events[event_name].event_id,events[event_name].event);
}
else {
events[event_name].event($(this));
}
if(events[event_name].expect_multiple) {
alert('here');
$(this).data('my_loader_'+events[event_name].event_id+'_executed',1);
}
});
//alert(events[event_name].obj_selector+' '+events[event_name].event_type);
if(!events[event_name].expect_multiple) {
delete events[event_name];
}
}
}
if(!html_is_loaded) {
var cur_time=new Date().getTime();
setTimeout('MY_loader().execute_events();',Math.max(Math.min(tick_time-(cur_time-last_tick_time),tick_time),0,min_tick_diff));
last_tick_time=cur_time;
}
}
this.html_is_loaded_set=function(if_html_is_loaded) {
html_is_loaded=if_html_is_loaded?true:false;
};
this.html_is_loaded_get=function() {
return html_is_loaded?true:false;
};
return this;
}
function instance(if_strat) {
if(typeof(class_is_loaded)=='undefined'||!class_is_loaded) {
load_class();
}
return container(if_strat);
}
var load_class=function() {
this.class_is_loaded=true;
this.events = {};
this.allowed_event_id_chars='abcdefghijklmnopqrstuvwxyz0123456789';
this.default_settings={
'event_type':'click',
'if_force':false,
'expect_multiple':false
};
this.tick_time=500;
this.min_tick_diff=100;
this.last_tick_time=0;
this.html_is_loaded=false;
MY_loader().execute_events();
$(document).ready(function(){
MY_loader().html_is_loaded_set(true);
MY_loader().execute_events(true);
});
}
var gen_new_event_id=function() {
for(var new_id=gen_random_id();typeof(events[new_id])!='undefined';new_id=gen_random_id());
return new_id;
}
var gen_random_id=function() {
var allowed_event_id_chars_size=allowed_event_id_chars.length;
var new_id='';
for(var i=0;i<10;i++) {
new_id+=allowed_event_id_chars[get_random_int(0,allowed_event_id_chars_size-1)];
}
return new_id;
}
function get_random_int(min, max)
{
return Math.floor(Math.random() * (max - min + 1)) + min;
}
return new instance();
}
//Add click event to #some_selector (once and dont check after it)
MY_loader().add_event(function() {
alert($(this).val());
}, '#some_selector');
//Hide elements as soon as they are loaded.
//We expect multiple elements with this selector, so it will
//check for this elements untill document is loaded, but this function
//will be applied only one time for each element.
MY_loader().add_event(function(obj) {
obj.hide();
alert('This should happen before DOM is completely loaded!');
}, '.some_other_selector',{'event_type':'func','expect_multiple':true});
//This alert should be outputted the last
$(document).ready(function(){
alert('Document is fully loaded!');
});
UPD: To make this question a little bit more interesting as it seems too specific I must add: most of the browsers start page rendering before it is completely loaded (this seems to be not well-known for some reason), here are a few links:
http://en.wikipedia.org/wiki/Incremental_rendering
When do browsers start to render partially transmitted HTML?
http://www.vbulletin.org/forum/showthread.php?t=161099
So, my problem should be more widely known as this incremental page loading adds lots of problems for developer: user can click on non-working buttons before page is loaded, some things that are hidden by JavaScript on load may show and they can be ugly, etc. (this are examples from my problem). Do other developers just ignore this problem? Please, correct me if I am wrong.
If your concern is that you don't want users to see the page before it is final, you can probably get away with doing the DOM modification straightaway, e.g.:
Test
<script type="text/javascript" src="enhancePage.js"></script>
Because the node in question exists in the DOM before the script is parsed, you can work with it.

How to focus main web page after opening a new window?

I want to be able to focus the original page after opening a new window/tab, the same way as it's done on this website: http://www.vouchercodes.co.uk/laredoute.co.uk
Its when you click on the green button 'Get code and open site'.
the code is all there for you to see. I used firebug to find the <a> object that had the click event bound to the code that did the popup behind the main browser window. I scrolled down to look inside the global.js file and found this:
Basically the .blur() on the named popup window will pass focus back to the main window for browsers that support it and return false; will ensure the link doesn't open in the current window which is the default behaviour. Scroll down the code below and you'll see it towards the bottom.
// -- VoucherClick --
// This baby does the funky stuff when the user clicks to reveal the voucher code
(function($) {
$.fn.extend({
voucherClick: function(config) {
return this.each(function() {
// What is the objects parent?
var theObject = $(this);
if ($(this).hasClass('the-image')) {
var theParent = theObject.parent().parent();
} else {
var theParent = theObject.parent().parent().parent();
}
theObject.click(function() {
// Revealed codes have a light yellow background
// First we remove the background of any currently selected vouchers
$('.selected-voucher').css('backgroundColor','#fff').removeClass('selected-voucher');
// Now we add the yellow background. We have to check what was clicked as it affects
// how far up the DOM tree the voucher DIV starts
// We also must check if we are on an indiviual page with an expired voucher,
// because the yellow background can overlap the left hand edge of the voucher
if (theParent.parent().hasClass('individual-expired')) {
} else {
theParent.css('backgroundColor','#ffffee').addClass('selected-voucher');
}
// Check to see if the voucher has alread been revealed - we only want to run this
// if it hasn't yet been clicked
if (!theParent.data('voucherRevealed')) {
// Make a note that this voucher has been clicked
theParent.data('voucherRevealed', true)
// Make a note of the voucher code and create the revealed code module
var thisCode = theParent.find('strong').html();
// If the code is over 18 characters, we need to reduce the font size
if (thisCode.length > 8) {
thisCode = '<span class="revealedVoucherCode small">' + thisCode + '</span>';
} else {
thisCode = '<span class="revealedVoucherCode">' + thisCode + '</span>';
}
// Fade out the initial module and fade in the revealed voucher module
theParent.find('.code-wrapper').fadeOut('normal', function() {
// If it's an individual page there is no H3
if (theParent.find('h3').length == 0){
// So we add the revealed module after the dates
theParent.find('.dates').after('<div class="revealedVoucher">' + thisCode + '</div>');
} else {
theParent.find('h3').after('<div class="revealedVoucher">' + thisCode + '</div>');
}
theParent.find('.revealedVoucher').fadeIn();
})
}
// Open the merchant link in a new window
var mer_window = window.open(theObject.attr('href'), '_blank', 'toolbar=1,location=1,directories=1,scrollbars=1,resizable=1,status=1,menubar=1');
// Where browsers support it, let's pop this new window BEHIND the current window
if (typeof mer_window === "object") {
mer_window.blur();
}
// Reveal the What Just Happened Text, which was set up in the VoucherInit function
theParent.find('.what-just-happened').slideDown();
// Don't open the link in this current window
return false;
}); // end theObject click function
}) // end this.each function
} // end function(config)
}) // end $.fn.extend
}) (jQuery);
based on the above example, I've put together the following code, however click event doesn't work...
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
<script type="text/javascript">
(function($) {
$.fn.extend({
myClick: function(config) {
return this.each(function() {
var theObject = $(this);
theObject.click(function() {
var new_window = window.open(theObject.attr('href'), '_blank', 'toolbar=1,location=1,directories=1,scrollbars=1,resizable=1,status=1,menubar=1');
if (typeof new_window === "object") {
new_window.blur();
}
return false;
});
})
}
})
}) (jQuery);
$('.fade').myClick();
</script>
</head>
<body>
Google<br />
</body>
</html>

Categories