This has been driving me nuts.
When i load a page i initiate a window.onfocus function:
initializeFocusDetecttor: function () {
window.onfocus = function () {
var options = {
useFade: false
}
$.OverWatch.worker.getView("/OverWatch/UpdateWatch", function () {
$.OverWatch.init();
}, options);
}
}
However I don't want this behavior on every page but I don't know how to remove/reset this.
I have tried
window.onfocus = null;
window.onfocus = function(){return;};
window.onfocus = "";
but it does not work
if you change it to use jQuery event handling, you can just remove it (e.g. with off).
initializeFocusDetecttor: function () {
$(window).on('focus.mine', function () {
var options = {
useFade: false
}
$.OverWatch.worker.getView("/OverWatch/UpdateWatch", function () {
$.OverWatch.init();
}, options);
});
});
// Some condition - turn it off
$(window).off('focus.mine');
This example adds the custom namespace .mine to the event name so that you can target it specifically without affecting other code using focus events.
Related
I am currently working on a javascript module which open and close boxes, tooltip or similar, the function works great the only problem is when I call it twice on a page where the 'boxes' classes are different the window mouseup event will be overwritten and only one of the two module instances of boxes can now be closed after opening them.
var boxRevealer = (function () {
var buttons;
var boxes;
var element;
var drp_active = false;
var boxConstruct = function (btns, bxs) {
buttons = document.querySelectorAll(btns);
boxes = document.querySelectorAll(bxs);
boxEvents();
};
var boxEvents = function () {
buttons.forEach(function (e) {
e.addEventListener("click", function (ee) {
element = document.getElementById(e.getAttribute("data-drp"));
element.classList.toggle("displayn");
drp_active = true;
});
});
window.addEventListener("mouseup", function (e) {
if (drp_active === true) {
if (!e.target.classList.contains("filt_holy")) {
boxes.forEach(function (e) {
console.log("ELEMENT");
console.log(e);
e.classList.add("displayn");
});
}
}
}, false);
};
return {
boxConstruct: boxConstruct,
boxEvents: boxEvents
};
})();
Here is how i call the module
window.addEventListener("load", function(e){
boxRevealer.boxConstruct(".head_drp_btn", ".head_drp");
boxRevealer.boxConstruct(".mkt_drp_btn", ".mkt_drp");
});
So my question is, should I always name the boxes the same, or is there a work around?
Just remove the event before adding it, I think the same event is getting called twice.
So updated code will be as follows:
// Attach an event handler to <div>
e.addEventListener("mousemove", myFunction);
// Remove the event handler from <div>
e.removeEventListener("mousemove", myFunction);
And remove the window event as well before adding it.
I have a local page to help in HTML and JavaScript that helps me with some basic tasks at work. I've been going back over my code and rewriting it to use best practices, since it helps me learn, and recently I've been trying to study namespacing and put it to use by rewriting the common page functions and event listeners.
window.onload = (function() {
var automationPageWrapper = (function() {
var self = {}
self.evntListeners = {
btnTextChange: function() {
// Code that changes button text when clicked
},
btnColorChange: function(formID) {
// Code that iterates through buttons with a certain name
// and makes them all the same default color
}
}
self.listeners = {
btnListeners: function() {
// Add all event listeners having to do with buttons here
}
}
return self;
});
automationPageWrapper.listeners.btnListeners();
});
Why isn't this attaching the event listeners?
Is there a better way to be formatting/calling this?
Is this a professional method for setting up JavaScript code?
I tested the event listeners by taking the functions and posting them into the Chrome console, so I think they work.
The full text, since some people like reading through all of it:
// Global namespace for the Page Functions
window.addEventListener("onload", function() {
var automationPageWrapper = (function() {
var self = {};
// Namespace for event listeners
self.evtListeners = {
// Function to change the color of a selected button
btnColorChange: function(formName) {
var elementsByName = document.getElementsByName(formName);
for (var i = 0; i < elementsByName.length; i++) {
if (elementsByName[i].className == "active") {
elementsByName[i].className = "inactive";
break;
}
}
},
// Add the event listeners
listeners: {
btnListeners: (function () {
document.getElementById('sidebar').addEventListener("click", function(e){
self.evtListeners.btnColorChange('sidebuttons');
e.target.className = "active";
});
})()
}
}
return self;
})();
automationPageWrapper.listeners.btnColorChange();
});
I'm still a little new to jQuery events.
I'm trying to write jQuery a wrapper/framework of the Asp.NET UpdatePanel that automatically tracks UpdatePanel async updates.
I want to be able to do something like
$("#myUpdatePanel").on("update", myFunc);
and have it run some handler with this as the updated UpdatePanel. I actually have this bit working.
I also want to be able run a function exactly once any time one or many UpdatePanels update.
$.updatePanel.on("update", myRunOnceFunc);
This is where I'm having issues.
I've defined my wrapper:
// wrap updatePanel reload functionality
$.updatePanel = (function () {
var prm;
var UpdatePanel = function () { };
UpdatePanel.prototype = { };
// initialize on $(document).ready()
$(function () {
prm = Sys.WebForms.PageRequestManager.getInstance();
if (prm) {
prm.add_pageLoaded(function (s, e) {
$.each(e.get_panelsUpdated(), function () {
// call panel-specific update event handlers
$(this).trigger($.Event("update"));
});
// triggered once no matter how many panels were updated
$(UpdatePanel).trigger($.Event("update"));
});
}
});
return $(UpdatePanel);
})();
Then in my code that uses $.updatePanel:
$(function() { $.updatePanel.on("update", myRunOnceFunc); });
What I'm finding is that myRunOnceFunc is being run during both $(this).trigger($.Event("update")); and $(UpdatePanel).trigger($.Event("update"));.
Any ideas why and how to fix it?
I figured out what was wrong.
Rather than return $(UpdatePanel);, I needed to call return $(new UpdatePanel());. Then I needed to replace $(UpdatePanel).trigger(...) with $.updatePanel.trigger(...). Code below:
// wrap updatePanel reload functionality
$.updatePanel = (function () {
var prm;
var UpdatePanel = function () { }
UpdatePanel.prototype = { };
$(function () {
prm = Sys.WebForms.PageRequestManager.getInstance();
if (prm) {
prm.add_pageLoaded(function (s, e) {
$.each(e.get_panelsUpdated(), function () {
$(this).trigger($.Event("update"));
});
// triggered once no matter how many panels were updated
$.updatePanel.trigger($.Event("update"));
});
}
});
return $(new UpdatePanel());
})();
I am playing around with a short little code to see if I can get a function going while the user has their mouse down and then end it when they bring their mouse up. For this example I am trying to increment a number that I am displaying on the screen as the user moves their mouse while holding the button down. I want it to freeze and stop once they release the button, however the counter just resets and the count continues from 0 even though the button is not being pressed...
function dragInit(state, e) {
var i = 0;
$(document).on("mousemove", function() {
if (state) {
i+=1;
$('#debug').text(i); //Show the value in a div
}
});
}
$(document).ready(function() {
$(document).on(
{mousedown: function(e) {
var state = true;
dragInit(e, state);
},
mouseup: function(e) {
var state = false;
dragInit(e, state);
}
});
});
As an aside, is there a way I can display whether a variable is true or false onscreen? When I try it just says [object Object].
There are a lot of mistakes in your code. I suggest you to read more basic concepts before starting to use jQuery.
The order of the parameters passed to dragInit() is wrong on both mouseup and mousedown event bindings.
The reason your counter is restarting is because your variable i is local, so it exists only during the function context it is declared in.
You are making the same mistake with the state variable, but in this case it is completely unnecessary to declare it.
Consider making your counter a global (even though it is not a good practice).
I can't provide you code because I am answering from my phone. A solution would be create a mousemove event that checkes whether the mouse button is pressed before incrementing your counter.
Hope I helped
You could do something like this:
function dragInit() {
$(document).on("mousemove", function () {
if (eventState.state) {
eventState.count += 1;
$('#debug').text(eventState.count); //Show the value in a div
}
});
}
// Create an object to track event variables
var eventState = {
count:0, //replaces your previous 'i' variable
state: false //keeps track of mouseup or mousedown
};
$(document).ready(function () {
$(document).on({
mousedown: function (e) {
eventState.state = true;
dragInit(); //don't need to pass anything anymore
},
mouseup: function (e) {
eventState.state = false;
dragInit(); //don't need to pass anything anymore
}
});
});
jsFiddle
Or keep everything together as one object
var dragInit = function () {
var count = 0;
var state = false;
var action = function () {
$(document).on("mousemove", function () {
if (state) {
count += 1;
$('#debug').text(count); //Show the value in a div
}
})
};
$(document).on({
mousedown: function (e) {
state = true;
action(); //don't need to pass anything anymore
},
mouseup: function (e) {
state = false;
action(); //don't need to pass anything anymore
}
});
}
$(document).ready(function () {
var obj = new dragInit();
});
jsFiddle 2
Example in response to comment
jsFiddle: This shows why the following code snippets differ in execution.
// Works
$(document).on("mousemove", function () {
if (state) {
}
})
// Doesn't
if (state) {
$(document).on("mousemove", function () {
});
}
Less code, You just need this.
Use jquery on and Off to turn on and off mousemove event.
Counter Reset http://jsfiddle.net/kRtEk/
$(document).ready(function () {
var i = 0;
$(document).on({
mousedown: function (e) {
$(document).on("mousemove", function () {
$('#debug').text(i++); //Show the value in a div
});
},
mouseup: function (e) {
i = 0;
$('#debug').text(i);
$(document).off("mousemove");
}
});
});
W/O Reset http://jsfiddle.net/gumwj/
$(document).ready(function () {
var i = 0;
$(document).on({
mousedown: function (e) {
$(document).on("mousemove", function () {
$('#debug').text(i++); //Show the value in a div
});
},
mouseup: function (e) {
$(document).off("mousemove");
}
});
});
WithNoCounter http://jsfiddle.net/F3ESx/
$(document).ready(function () {
$(document).on({
mousedown: function (e) {
$(document).on("mousemove", function () {
$('#debug').data('idx',parseInt($('#debug').data('idx')|0)+1).text($('#debug').data('idx')); //Show the value in a div
});
},
mouseup: function (e) {
$(document).off("mousemove");
}
});
});
Assuming you are married to Jquery (nothing wrong with that) - check out and consider entirely re-thinking your approach leveraging the ".one()" (http://api.jquery.com/one/) method.
edit: and if that taste doesn't sit well - familiarize yourself with the "deferred" object (http://api.jquery.com/category/deferred-object/)
lots of ways to approach this via jquery - what you decide in the end depends on what you really intend to do with this.
I'm looking for a super simple jQuery extension. Basically I need to use some events that jQuery does not explicitly support. These events are the iPhone touch events like ontouchstart, ontouchend, and ontouchmove.
I have it working via this:
// Sucks
$('.clickable').each(function() {
this.ontouchstart = function(event) {
//do stuff...
};
}
Which kind of sucks and is unjqueryish. Here is what I would like:
// Better
$('.clickable').touchstart(function() {
//do stuff...
}
Or even better with 1.4
// Awesome
$('.clickable').live('touchstart', function() {
//.. do stuff
}
These events need no special handling and should work just like any other events, but I can't seem to figure out how to extend jquery to make them work just like all the other events do.
I wrote the plugin, if the user does have touch available, use, otherwise, call click
jQuery.event.special.tabOrClick = {
setup: function (data, namespaces) {
var elem = this, $elem = jQuery(elem);
if (window.Touch) {
$elem.bind('touchstart', jQuery.event.special.tabOrClick.onTouchStart);
$elem.bind('touchmove', jQuery.event.special.tabOrClick.onTouchMove);
$elem.bind('touchend', jQuery.event.special.tabOrClick.onTouchEnd);
} else {
$elem.bind('click', jQuery.event.special.tabOrClick.click);
}
},
click: function (event) {
event.type = "tabOrClick";
jQuery.event.handle.apply(this, arguments);
},
teardown: function (namespaces) {
var elem = this, $elem = jQuery(elem);
if (window.Touch) {
$elem.unbind('touchstart', jQuery.event.special.tabOrClick.onTouchStart);
$elem.unbind('touchmove', jQuery.event.special.tabOrClick.onTouchMove);
$elem.unbind('touchend', jQuery.event.special.tabOrClick.onTouchEnd);
} else {
$elem.unbind('click', jQuery.event.special.tabOrClick.click);
}
},
onTouchStart: function (e) {
this.moved = false;
},
onTouchMove: function (e) {
this.moved = true;
},
onTouchEnd: function (event) {
if (!this.moved) {
event.type = "tabOrClick";
jQuery.event.handle.apply(this, arguments)
}
}
};
$("#xpto").bind("tabOrClick", function () {
alert("aaaa");
});
I've made a small update to Alexandre's plugin to include Android support. Android's browser does not currently support the window.Touch method of detecting touch support.
I love how Alexandre's script waits to ensure movement didn't occur to prevent triggering the event when the user swipes to scroll across the screen. However a downfall of that approach is that it causes its own delay by waiting for the user to lift their finger off of the screen before triggering. I've updated his plugin to include a "touchactive" class that gets applied to items that a user is currently touching. If you take advantage of that class you can provide immediate visual feedback to users without causing an actual event to get triggered until after movement check has completed.
jQuery.event.special.touchclick = {
setup: function (data, namespaces) {
var elem = this, $elem = jQuery(elem);
var ua = navigator.userAgent.toLowerCase();
var isAndroid = ua.indexOf("android") > -1;
if (window.Touch || isAndroid) {
$elem.bind('touchstart', jQuery.event.special.touchclick.onTouchStart);
$elem.bind('touchmove', jQuery.event.special.touchclick.onTouchMove);
$elem.bind('touchend', jQuery.event.special.touchclick.onTouchEnd);
} else {
$elem.bind('click', jQuery.event.special.touchclick.click);
}
},
click: function (event) {
event.type = "touchclick";
jQuery.event.handle.apply(this, arguments);
},
teardown: function (namespaces) {
var elem = this, $elem = jQuery(elem);
if (window.Touch) {
$elem.unbind('touchstart', jQuery.event.special.touchclick.onTouchStart);
$elem.unbind('touchmove', jQuery.event.special.touchclick.onTouchMove);
$elem.unbind('touchend', jQuery.event.special.touchclick.onTouchEnd);
} else {
$elem.unbind('click', jQuery.event.special.touchclick.click);
}
},
onTouchStart: function (e) {
this.moved = false;
$(this).addClass('touchactive');
},
onTouchMove: function (e) {
this.moved = true;
$(this).removeClass('touchactive');
},
onTouchEnd: function (event) {
if (!this.moved) {
event.type = "touchclick";
jQuery.event.handle.apply(this, arguments)
}
$(this).removeClass('touchactive');
}
};
I've also posted this to github in case there are further caveats that are discovered https://github.com/tuxracer/jquery-touchclick
This now works, just like it's stubbed out above, on the latest jQuery release. Go jQuery!
Here's a start:
$.fn.touchstart = function(fn) { return this[fn ? "bind" : "trigger"]("touchstart", fn); };
$.event.special.touchstart = {
setup: function() {
$.event.add(this, "mouseenter", extendedClickHandler, {});
},
teardown: function() {
$.event.remove(this, "mouseenter", extendedClickHandler);
}
};
Where extendedClickHandler is the function that does what it's suppose to do.
More info here: http://brandonaaron.net/blog/2009/03/26/special-events
jQuery.com is a great source of information like this.
If you build your own plugin you'll be able to use whatever naming you like on your method calls.