IE fires onresize when body resizes - javascript

I have the following function - it works fine in Firefox:
How I can I get this to fire on body resize in IE??
function sizeColumnHeadings() {
var $headingsTable = $('#TopicPostList_hdiv > table').eq(0),
$rowsTable = $('#TopicPostList_div > table').eq(0);
if ($headingsTable.length && $rowsTable.length) {
$headingsTable.width($rowsTable.width());
}
}
$(window).on('resize', function() {
sizeColumnHeadings();
}).trigger('resize');

If you use jquery, I found the following code works in IE, Firefox and Chrome.
var cnt = 0;
// this is called when the document finishes loading (similar to onLoad in the body tag)
$(function() {
// this asssigns a callback function each time the browser is resized
// it turns out that it is triggered multiple times on one resize
$(window).resize(function() {
cnt++;
// this code simply displays the # of times the callback is triggered
// I defined a <div id=show> in the body, and this updates its html.
$('#show').html('cnt = ' + cnt);
});
});
I recommend using jquery for this sort of problem, as it often takes care of the incompatibilities between different browser.

Related

How to start javascript setinterval once cleared?

I have a setinterval that runes every 5 seconds. this works fine on page load.
I have the following scenarios:
Load page with interval (WORKS)
press button and load new content and stopp interval(WORKS)
Once the new content is no longer desiered, dissmiss it, return to first content and start interval again(DOES NOT WORK)
I have saftys suchs as events for window.blur that also stops the interval so that the browser does not commponsate for all the missing intervals if i would change tabs or something. Keep in mind that step 3 did not work BUT if i would after step 3 change a tab and then return to my original page(execute blur) the interval would start working again.
NOTE all content loading here exept page load is done with ajax calls.
My code:
initializing:
$.automation.worker.bindIntervalEvent("#TanksContent", "/Tank/GetTanks", function() {
$.automation.tanks.tableInit();
});
binding function:
bindIntervalEvent: function (target, url, callback) {
$(window)
.on("focus.mine",
function() {
$.automation.worker.setUpdateInterval(target, url, callback);
})
.on("blur",
function() {
$.automation.worker.stopUpdateInterval();
}).trigger("focus.mine");
}
interval function:
setUpdateInterval: function (target, url, callback) {
if ($.automation.globals.globalInterval.value.length === 0) {
$.automation.globals.globalInterval.value.push(window.setInterval(
function () {
var options = {
loadTarget: target
}
$.automation.worker.getView(url,
function() {
if (callback)
callback();
},
options);
},
5000));
}
}
the function that stops the interval:
stopUpdateInterval: function () {
if ($.automation.globals.globalInterval.value.length === 0)
return;
console.log("deleting");
for (var i = 0; i <= $.automation.globals.globalInterval.value.length; i++) {
window.clearInterval($.automation.globals.globalInterval.value[i])
$.automation.globals.globalInterval.value.splice(i, 1);
console.log($.automation.globals.globalInterval.value.length);
}
}
when stopping the interval i also remove the window bindings:
unBindIntervalEvent: function() {
$(window).off("focus.mine");
$(window).unbind("blur");
}
Back to step 3:
My sucess method in the callback to my getviewfunction is identical to what i execute in the beginning
code:
$(".updatelatest")
.on("click",
function () {
var _this = $(this);
var options = {
loadTarget:"#TanksContent"
}
$.automation.worker.getView("/Tank/GetTanks",
function (data) {
$(_this).switchClass("col-md-5", "col-md-1", 1000, function() {
$(_this).addClass("hidden");
$(".search").switchClass("col-md-5", "col-md-12", 1000, "easeInOutQuad");
})
$.automation.tanks.tableInit();
$.automation.worker.bindIntervalEvent("#TanksContent", "/Tank/GetTanks", function () {
$.automation.tanks.tableInit();
});
$(window).trigger("blur");
}, options);
});
but this does not start the interval. it is clearly initialized since it works when window.blur is executed for example when I change tab but for some reason this is not working beyond that.
i tried triggering the windows blur event and nothing happened, i tried triggering my custom window event "focuse.mine" but nothing happens.
I did not notice this while developing since I had firebug open and every time i checked scripts or css or the console the blur function was executed so I assumed that my code worked as intended but now that it is deployed I notice this.
My head is pounding beyond reason and I can't for figure out where I have gone wrong.
Well this was a fun one. I simply found that when calling the setUpdateInterval(); function directly it gave me the desiered result.
I realized that the reason I had them split like I did was becaouse of the blur event. "Focus.mine" is triggered to start the inteval again ocne a user comes back to the page.

JavaScript on resize and load, move element based on window width

I'm trying to move an element to an off canvas menu if the window width is less than 768px wide.
So far I have this:
<script>
window.onresize = move_sidebar(event);
window.onload = move_sidebar(event);
function move_sidebar(event) {
if(window.outerWidth > 768) {
return;
} else {
console.log('resized or loaded');
document.getElementById('offcanvas-menu').appendChild(document.getElementById('sidebar-content'));
}
}
</script>
When the window loads it works fine, the console log is shown and the element is moved, however, when I resize the window the event doesn't fire.
Unless I do:
window.onresize = function(event) { console.log('resizing'); };
This then logs each time the window is resized, I'm unable to figure out why there's a difference between the two.
I also need to move the element back to its original place if the width is greater than 768px, as long as it only exists in the offcanvas-menu element.
Any ideas?
EDIT:
I ended up fixing this with the following code:
<script>
window.onresize = move_sidebar;
window.onload = move_sidebar;
function move_sidebar(event) {
ele = document.getElementById('sidebar-content');
if(window.outerWidth > 768) {
if(ele.parentNode.id == 'offcanvas-menu') {
document.getElementById('sidebar').appendChild(document.getElementById('sidebar-content'));
}
return;
} else {
document.getElementById('offcanvas-menu').appendChild(ele);
}
}
</script>
You are passing as the event handler the result of you move_sidebar function after execution, instead of passing the function itself.
Your code should be:
window.onresize = move_sidebar;
window.onload = move_sidebar;
The reason it works for you when the page loads is only because you have manually executed your function by mistake.

BigVideo.js .on("ended") fires multiple times

I'm using BigVideo.js jQuery plugin to show full screen background videos. I have links that load different background videos on click. At the end of each video (3-5 sec long) I'm loading an animation. Each video has its own animation on top.
Right now I'm fading in the animations with a time out that corresponds to the video length but it's not full proof. What I really need is for #anim03 to fade in when video-03.mp4 ends. But I can't figure out exactly how the BigVideo.js .on("ended") event really works. In the code I have below (simplified):
// init plugin
var BV = new $.BigVideo({useFlashForFirefox:false});
BV.init();
function setupVideo(url) {
if (Modernizr.touch) {
BV.show(url + '.jpg');
} else {
BV.show(url + '.mp4',{
altSource: url + '.webm',
ambient: false
});
}
}
function setupAnimation(num) {
BV.getPlayer().on("ended", function () { // event from video.js API - when video ends playing
$('#anim0' + num).animate({ opacity: 1 });
});
}
$('a').on('click', function(e) {
e.preventDefault();
// we remove .ext cause we got to setup .webm and .jpg versions
var url = $(this).attr('href').replace('.mp4', '');
setupVideo(url);
var current = $(this).parent().index()+1;
setupAnimation(current);
});
The event is triggered but it seems to go through some sort of queue and fire multiple times. If I console.log num like that:
function setupAnimation(num) {
console.log(num);
BV.getPlayer().on("ended", function () {
$('#anim0' + num).animate({ opacity: 1 });
});
}
I get a single expected value. But if I do it like that:
function setupAnimation(num) {
BV.getPlayer().on("ended", function () {
console.log(num);
$('#anim0' + num).animate({ opacity: 1 });
});
}
Then I get multiple values for num and each time I click and this function is called, I get more and moreā€¦ I'm guessing this .on("ended") loops through some array or something? I can't figure out that part from looking at the plugin's code.
Any help or pointer much appreciated!
When you use the player's "on" function you register a new listener function (This gives you the possibility to trigger multiple functions when something happens).
The reason your on "ended" function fires multiple times, is because each time setupAnimation executed it adds a new instance of the listener-function:
function () {
console.log(num);
$('#anim0' + num).animate({ opacity: 1 });
}
check the API documentation of Video.JS
https://github.com/videojs/video.js/blob/master/docs/api/vjs.Player.md#on-type-fn-
If I get right what you're trying to accomplish, the solution is to run 'setupAnimation' outside the on 'click' function.

Timed long press in Javascript within jQuery phonegap app

There is a good example for doing long press in Javascript here: Long Press in JavaScript?
But it does not provide for knowing the duration of the press.
If I want to do different things based on the length of the press I cant use the pattern in that post.
I was trying to do something similar by saving current time in a variable on('mousedown')
and then calculating the time difference on('mouseup').
this works fine within a normal Javasript page in a "normal" browser.
However within my phonegap app something happens,
looks like the mouseup event is not being called if the finger is kept on the screen for a long duration (say 5 sec..).
Is this some native mobile browser behavior? Can I override it somehow?
I am using plain jQuery not jQuery mobile.
Any ideas anyone?
You could have a look at how the taphold and vmouseup (handleTouchEnd() line 752) events are implemented in jQuery mobile source code.
Since it is already tested and implemented I'd suggest to use jquery mobile instead of jquery and modify (since it already handles all the 'quirks' related each mobile browser), and change the code as you need.
You can check the time to identify Click or Long Press [jQuery]
function AddButtonEventListener() {
try {
var mousedowntime;
var presstime;
$("button[id$='" + buttonID + "']").mousedown(function() {
var d = new Date();
mousedowntime = d.getTime();
});
$("button[id$='" + buttonID + "']").mouseup(function() {
var d = new Date();
presstime = d.getTime() - mousedowntime;
if (presstime > 999/*You can decide the time*/) {
//Do_Action_Long_Press_Event();
}
else {
//Do_Action_Click_Event();
}
});
}
catch (err) {
alert(err.message);
}
}
Note that this solution is usefull if you do not use jQuery Mobile for some reason.
I used the article Fast Touch Event Handling and just added a piece of code
$.event.special.tap = {
distanceThreshold: 10,
timeThreshold: 350,
setup: function () {
var self = this,
$self = $(self);
// Bind touch start
$self.on('touchstart', function (startEvent) {
// Save the target element of the start event
var target = startEvent.target,
touchStart = startEvent.originalEvent.touches[0],
startX = touchStart.pageX,
startY = touchStart.pageY,
threshold = $.event.special.tap.distanceThreshold,
timeout,
expired = false;
function timerFired() {
expired = true;
}
function removeTapHandler() {
clearTimeout(timeout);
$self.off('touchmove', moveHandler).off('touchend', tapHandler).off('touchcancel', removeTapHandler);
};
function tapHandler(endEvent) {
removeTapHandler();
if (target == endEvent.target) {
if (expired) {
$.event.simulate('longtap', self, endEvent);
} else {
$.event.simulate('tap', self, endEvent);
}
}
};
// Remove tap and move handlers if the touch moves too far
function moveHandler(moveEvent) {
var touchMove = moveEvent.originalEvent.touches[0],
moveX = touchMove.pageX,
moveY = touchMove.pageY;
if (Math.abs(moveX - startX) > threshold || Math.abs(moveY - startY) > threshold) {
removeTapHandler();
}
};
// Remove the tap and move handlers if the timeout expires
timeout = setTimeout(timerFired, $.event.special.tap.timeThreshold);
// When a touch starts, bind a touch end and touch move handler
$self.on('touchmove', moveHandler).on('touchend', tapHandler).on('touchcancel', removeTapHandler);
});
}
};
So, now I have a tap and a longtap events

Firefox does not report exception when using JavaScript DOMContentLoaded with document.addEventListener

I am writing an internal framework that can have no dependencies (i.e. jQuery, etc.) and am trying to implement my own DOM ready-style functionality. It seems that when a callback in the ready queue (array of callbacks to complete on DOM ready), if an exception is thrown inside that function, execution stops and continues onto the next callback (which is what I want), but Firefox will not report the error (log to the console, trigger onerror, anything). Am I doing something wrong?
I have implemented this using a combination of a pattern by Dean Edwards (http://dean.edwards.name/weblog/2009/03/callbacks-vs-events/) and the jQuery source. I do not wish to implement just like jQuery because if one callback fails, the subsequent callbacks won't execute.
var readyCallbacks = [];
(function () {
var currentHandler,
fireReady,
removeEvents,
loopCallbacks = function () {
for (var i = 0, len = readyCallbacks.length; i < len; i += 1) {
currentHandler = readyCallbacks[i];
fireReady();
}
};
if (document.addEventListener) {
document.addEventListener('readyEvents', function () { currentHandler(); }, false);
fireReady = function () {
var readyEvent = document.createEvent('UIEvents');
readyEvent.initEvent('readyEvents', false, false);
document.dispatchEvent(readyEvent);
};
removeEvents = function () {
window.removeEventListener('load', loopCallbacks, false);
loopCallbacks();
};
document.addEventListener('DOMContentLoaded', removeEvents, false);
window.addEventListener('load', loopCallbacks, false);
} else {
// if < IE 9
document.documentElement.readyEvents = 0;
document.documentElement.attachEvent('onpropertychange', function (e) {
if (e.propertyName === 'readyEvents')
currentHandler();
});
fireReady = function () {
document.documentElement.readyEvents += 1;
};
removeEvents = function () {
window.detachEvent('onload', loopCallbacks);
loopCallbacks();
};
document.attachEvent('onreadystatechange', removeEvents);
window.attachEvent('onload', loopCallbacks);
}
})();
Client.ready = function (callback) {
readyCallbacks.push(callback);
};
Here is my test implementation. The console is written to and the DOM element has been manipulated. In IE error with the UNDEFINED_VARIABLE++; is shown in the console, but not in Firefox.
<!DOCTYPE html>
<html>
<head>
<script src="Client.js"></script>
<script>
Client.ready(function () {
console.log('logging before error');
UNDEFINED_VARIABLE++; // This does not error in Firefox
console.log('logging after error, not logged in Firefox');
});
Client.ready(function () {
console.log('before DOM access');
document.getElementById('cheese').innerHTML = 'cheese';
console.log('after DOM access');
});
</script>
</head>
<body>
<div id="cheese">test</div>
</body>
</html>
After some searching, this appears to be a known Mozilla bug: Errors thrown by handlers for custom events dispatched via dispatchEvent() are not logged properly in some versions of Firefox 3.x. This isn't a problem in your code, but in the browser implementation. If it's a real problem for you, you can wrap the handler in a try/catch block to identify and deal with errors:
document.addEventListener('readyEvents', function() {
try { currentHandler() } catch (e) { console.log(e) }
}, false);
I have a jsFiddle here that demonstrates the problem with a simplified set of tests. Firefox correctly logs errors on handlers for built-in events like DOMContentLoaded and load, but misses the error when firing a handler for a custom event.
It's hard to get it right. See the jQuery source code and search for ready to see how it is implemented in a portable way. Keep in mind that you have to make sure that when you bind ready handlers after the dom is already ready then you have to call them straight away or else they won't be called at all. See also this question.

Categories